glamor_pixmap_upload_texture: Support to upload a sub region of data.

Just as the downloading side, we can upload an sub region data to
a pixmap's specified region. The data could be in memory or in a
pbo buffer.

Signed-off-by: Zhigang Gong <zhigang.gong@linux.intel.com>
This commit is contained in:
Zhigang Gong 2012-04-10 20:50:14 +08:00 committed by Eric Anholt
parent 3061f348ca
commit b0e91f0f5a
3 changed files with 96 additions and 135 deletions

View File

@ -406,66 +406,60 @@ glamor_color_convert_to_bits(void *src_bits, void *dst_bits, int w, int h, int s
**/
int in_restore = 0;
static void
__glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format,
GLenum type, GLuint tex, int sub,
void *bits)
__glamor_upload_pixmap_to_texture(PixmapPtr pixmap, int *tex,
GLenum format,
GLenum type,
int x, int y, int w, int h,
void *bits, int pbo)
{
glamor_pixmap_private *pixmap_priv =
glamor_get_pixmap_private(pixmap);
glamor_screen_private *glamor_priv =
glamor_get_screen_private(pixmap->drawable.pScreen);
glamor_gl_dispatch *dispatch;
unsigned int stride, row_length;
GLenum iformat;
if (glamor_priv->gl_flavor == GLAMOR_GL_ES2)
iformat = format;
else
gl_iformat_for_depth(pixmap->drawable.depth, &iformat);
stride = pixmap->devKind;
row_length = (stride * 8) / pixmap->drawable.bitsPerPixel;
dispatch = glamor_get_dispatch(glamor_priv);
dispatch->glBindTexture(GL_TEXTURE_2D, tex);
if (*tex == 0) {
int iformat;
dispatch->glGenTextures(1, tex);
if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
gl_iformat_for_depth(pixmap->drawable.depth, &iformat);
else
iformat = format;
dispatch->glBindTexture(GL_TEXTURE_2D, *tex);
dispatch->glTexImage2D(GL_TEXTURE_2D,
0,
iformat,
w, h, 0, format, type,
bits);
} else
dispatch->glBindTexture(GL_TEXTURE_2D, *tex);
dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_NEAREST);
dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_NEAREST);
if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
} else {
dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
}
dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
if (bits == NULL)
dispatch->glBindBuffer(GL_PIXEL_UNPACK_BUFFER,
pixmap_priv->fbo->pbo);
pbo);
if (sub)
dispatch->glTexSubImage2D(GL_TEXTURE_2D,
0,0,0,
pixmap->drawable.width,
pixmap->drawable.height, format, type,
bits);
else
dispatch->glTexImage2D(GL_TEXTURE_2D,
0,
iformat,
pixmap->drawable.width,
pixmap->drawable.height, 0, format, type,
bits);
dispatch->glTexSubImage2D(GL_TEXTURE_2D,
0, x, y, w, h,
format, type,
bits);
if (bits == NULL)
dispatch->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
glamor_put_dispatch(glamor_priv);
}
Bool
glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format, GLenum type,
int no_alpha, int revert, int swap_rb, void *bits)
static Bool
_glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format, GLenum type,
int no_alpha, int revert,
int swap_rb, int x, int y, int w, int h,
int stride, void* bits, int pbo)
{
glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen);
@ -483,7 +477,7 @@ glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format, GLenum typ
};
float *ptexcoords;
float dst_xscale, dst_yscale;
GLuint tex;
GLuint tex = 0;
int need_flip;
int need_free_bits = 0;
@ -496,12 +490,11 @@ glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format, GLenum typ
&& revert > REVERT_NORMAL) {
/* XXX if we are restoring the pixmap, then we may not need to allocate
* new buffer */
void *converted_bits = malloc(pixmap->drawable.height * pixmap->devKind);
void *converted_bits = malloc(h * stride);
if (converted_bits == NULL)
return FALSE;
bits = glamor_color_convert_to_bits(bits, converted_bits, pixmap->drawable.width,
pixmap->drawable.height,
pixmap->devKind,
bits = glamor_color_convert_to_bits(bits, converted_bits, w, h,
stride,
no_alpha, revert, swap_rb);
if (bits == NULL) {
ErrorF("Failed to convert pixmap no_alpha %d, revert mode %d, swap mode %d\n", swap_rb);
@ -520,9 +513,11 @@ ready_to_upload:
&& revert == REVERT_NONE
&& swap_rb == SWAP_NONE_UPLOADING
&& !need_flip) {
__glamor_upload_pixmap_to_texture(pixmap, format, type,
pixmap_priv->fbo->tex, 1,
bits);
assert(pixmap_priv->fbo->tex);
__glamor_upload_pixmap_to_texture(pixmap, &pixmap_priv->fbo->tex,
format, type,
x, y, w, h,
bits, pbo);
return TRUE;
}
@ -534,8 +529,8 @@ ready_to_upload:
pixmap_priv_get_scale(pixmap_priv, &dst_xscale, &dst_yscale);
glamor_set_normalize_vcoords(dst_xscale,
dst_yscale,
0, 0,
pixmap->drawable.width, pixmap->drawable.height,
x, y,
x + w, y + h,
glamor_priv->yInverted,
vertices);
@ -551,9 +546,10 @@ ready_to_upload:
dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
glamor_set_destination_pixmap_priv_nc(pixmap_priv);
dispatch->glGenTextures(1, &tex);
__glamor_upload_pixmap_to_texture(pixmap, format, type, tex, 0, bits);
__glamor_upload_pixmap_to_texture(pixmap, &tex,
format, type,
0, 0, w, h,
bits, pbo);
dispatch->glActiveTexture(GL_TEXTURE0);
dispatch->glBindTexture(GL_TEXTURE_2D, tex);
@ -589,40 +585,6 @@ ready_to_upload:
return TRUE;
}
/*
* Load texture from the pixmap's data pointer and then
* draw the texture to the fbo, and flip the y axis.
* */
static Bool
_glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format,
GLenum type, int no_alpha, int revert,
int swap_rb)
{
glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen);
void *bits;
int need_free_bits = 0;
if (!pixmap_priv)
return TRUE;
glamor_debug_output(GLAMOR_DEBUG_TEXTURE_DYNAMIC_UPLOAD,
"Uploading pixmap %p %dx%d depth%d.\n",
pixmap,
pixmap->drawable.width,
pixmap->drawable.height,
pixmap->drawable.depth);
if (pixmap_priv->fbo->pbo && pixmap_priv->fbo->pbo_valid)
bits = NULL;
return glamor_upload_bits_to_pixmap_texture(pixmap, format, type, no_alpha,
revert, swap_rb,
pixmap->devPrivate.ptr);
}
/*
* Prepare to upload a pixmap to texture memory.
* no_alpha equals 1 means the format needs to wire alpha to 1.
@ -642,6 +604,9 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha, int
pixmap_priv = glamor_get_pixmap_private(pixmap);
glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen);
if (pixmap_priv && pixmap_priv->fbo && pixmap_priv->fbo->fb)
return 0;
if (!(no_alpha
|| (revert != REVERT_NONE)
|| (swap_rb != SWAP_NONE_UPLOADING)
@ -683,8 +648,9 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha, int
return 0;
}
enum glamor_pixmap_status
glamor_upload_pixmap_to_texture(PixmapPtr pixmap)
Bool
glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w, int h,
int stride, void *bits, int pbo)
{
GLenum format, type;
int no_alpha, revert, swap_rb;
@ -697,14 +663,40 @@ glamor_upload_pixmap_to_texture(PixmapPtr pixmap)
&swap_rb, 1)) {
glamor_fallback("Unknown pixmap depth %d.\n",
pixmap->drawable.depth);
return GLAMOR_UPLOAD_FAILED;
return TRUE;
}
if (glamor_pixmap_upload_prepare(pixmap, format, no_alpha, revert, swap_rb))
return GLAMOR_UPLOAD_FAILED;
return FALSE;
if (_glamor_upload_pixmap_to_texture(pixmap, format, type, no_alpha,
revert, swap_rb))
return _glamor_upload_bits_to_pixmap_texture(pixmap, format, type, no_alpha, revert, swap_rb,
x, y, w, h, stride, bits, pbo);
}
enum glamor_pixmap_status
glamor_upload_pixmap_to_texture(PixmapPtr pixmap)
{
glamor_pixmap_private *pixmap_priv;
void *data;
int pbo;
pixmap_priv = glamor_get_pixmap_private(pixmap);
if (pixmap_priv
&& (pixmap_priv->fbo)
&& (pixmap_priv->fbo->pbo_valid)) {
data = NULL;
pbo = pixmap_priv->fbo->pbo;
} else {
data = pixmap->devPrivate.ptr;
pbo = 0;
}
if (glamor_upload_sub_pixmap_to_texture(pixmap, 0, 0,
pixmap->drawable.width,
pixmap->drawable.height,
pixmap->devKind,
data, pbo))
return GLAMOR_UPLOAD_DONE;
else
return GLAMOR_UPLOAD_FAILED;
@ -715,20 +707,7 @@ glamor_upload_pixmap_to_texture(PixmapPtr pixmap)
void
glamor_restore_pixmap_to_texture(PixmapPtr pixmap)
{
GLenum format, type;
int no_alpha, revert, swap_rb;
if (glamor_get_tex_format_type_from_pixmap(pixmap,
&format,
&type, &no_alpha,
&revert, &swap_rb, 1)) {
ErrorF("Unknown pixmap depth %d.\n",
pixmap->drawable.depth);
assert(0);
}
if (!_glamor_upload_pixmap_to_texture(pixmap, format, type, no_alpha,
revert, swap_rb))
if (glamor_upload_pixmap_to_texture(pixmap) != GLAMOR_UPLOAD_DONE)
LogMessage(X_WARNING, "Failed to restore pixmap to texture.\n",
pixmap->drawable.pScreen->myNum);
}

View File

@ -639,6 +639,10 @@ glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag);
enum glamor_pixmap_status glamor_upload_pixmap_to_texture(PixmapPtr
pixmap);
Bool
glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w, int h,
int stride, void *bits, int pbo);
PixmapPtr
glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y,

View File

@ -263,10 +263,7 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
int x_off, y_off;
float vertices[8], texcoords[8];
GLfloat xscale, yscale, txscale, tyscale;
GLuint tex;
int no_alpha, revert;
Bool ret = FALSE;
int swap_rb;
PixmapPtr temp_pixmap;
glamor_pixmap_private *temp_pixmap_priv;
@ -288,37 +285,19 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
if (!glamor_set_planemask(pixmap, gc->planemask)) {
goto fail;
}
if (glamor_get_tex_format_type_from_pixmap(pixmap,
&format,
&type, &no_alpha,
&revert,
&swap_rb,
1)) {
glamor_fallback("unknown depth. %d \n", drawable->depth);
goto fail;
}
/* create a temporary pixmap and upload the bits to that
* pixmap, then apply clip copy it to the destination pixmap.*/
temp_pixmap = glamor_create_pixmap(drawable->pScreen, w, h, depth, 0);
if (temp_pixmap == NULL)
goto fail;
temp_pixmap_priv = glamor_get_pixmap_private(temp_pixmap);
temp_pixmap_priv->pict_format = pixmap_priv->pict_format;
temp_pixmap_priv->is_picture = pixmap_priv->is_picture;
if (temp_pixmap_priv->fbo == NULL) {
glamor_destroy_pixmap(temp_pixmap);
goto fail;
}
if (!glamor_upload_bits_to_pixmap_texture(temp_pixmap, format, type,
no_alpha, revert, swap_rb, bits)) {
glamor_destroy_pixmap(temp_pixmap);
goto fail;
}
glamor_upload_sub_pixmap_to_texture(temp_pixmap, 0, 0, w, h,
pixmap->devKind, bits, 0);
dispatch = glamor_get_dispatch(glamor_priv);
if (!glamor_set_alu(dispatch, gc->alu)) {
@ -345,9 +324,9 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
#endif
dispatch->glUseProgram(glamor_priv->finish_access_prog[0]);
dispatch->glUniform1i(glamor_priv->
finish_access_revert[no_alpha],
finish_access_revert[0],
REVERT_NONE);
dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha],
dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[0],
SWAP_NONE_UPLOADING);
x += drawable->x;
@ -397,7 +376,6 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
dispatch->glDeleteTextures(1, &tex);
if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glamor_set_alu(dispatch, GXcopy);