meta_tex_subimage.c revision 3071da303211701df38ee052cb80c30acba51768
1/* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 2015 Intel Corporation. All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included 14 * in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: 25 * Jason Ekstrand <jason.ekstrand@intel.com> 26 */ 27 28#include "blend.h" 29#include "bufferobj.h" 30#include "buffers.h" 31#include "clear.h" 32#include "fbobject.h" 33#include "framebuffer.h" 34#include "glformats.h" 35#include "glheader.h" 36#include "image.h" 37#include "macros.h" 38#include "meta.h" 39#include "pbo.h" 40#include "readpix.h" 41#include "shaderapi.h" 42#include "state.h" 43#include "teximage.h" 44#include "texobj.h" 45#include "texstate.h" 46#include "uniforms.h" 47#include "varray.h" 48 49static bool 50need_signed_unsigned_int_conversion(mesa_format mesaFormat, 51 GLenum format, GLenum type) 52{ 53 const GLenum mesaFormatType = _mesa_get_format_datatype(mesaFormat); 54 const bool is_format_integer = _mesa_is_enum_format_integer(format); 55 return (mesaFormatType == GL_INT && 56 is_format_integer && 57 (type == GL_UNSIGNED_INT || 58 type == GL_UNSIGNED_SHORT || 59 type == GL_UNSIGNED_BYTE)) || 60 (mesaFormatType == GL_UNSIGNED_INT && 61 is_format_integer && 62 (type == GL_INT || 63 type == GL_SHORT || 64 type == GL_BYTE)); 65} 66 67static struct gl_texture_image * 68create_texture_for_pbo(struct gl_context *ctx, 69 bool create_pbo, GLenum pbo_target, 70 int dims, int width, int height, int depth, 71 GLenum format, GLenum type, const void *pixels, 72 const struct gl_pixelstore_attrib *packing, 73 struct gl_buffer_object **tmp_pbo, GLuint *tmp_tex) 74{ 75 uint32_t pbo_format; 76 GLenum internal_format; 77 unsigned row_stride; 78 struct gl_buffer_object *buffer_obj; 79 struct gl_texture_object *tex_obj; 80 struct gl_texture_image *tex_image; 81 bool read_only; 82 83 if (packing->SwapBytes || 84 packing->LsbFirst || 85 packing->Invert) 86 return NULL; 87 88 pbo_format = _mesa_format_from_format_and_type(format, type); 89 if (_mesa_format_is_mesa_array_format(pbo_format)) 90 pbo_format = _mesa_format_from_array_format(pbo_format); 91 92 if (!pbo_format || !ctx->TextureFormatSupported[pbo_format]) 93 return NULL; 94 95 /* Account for SKIP_PIXELS, SKIP_ROWS, ALIGNMENT, and SKIP_IMAGES */ 96 uint32_t first_pixel = _mesa_image_offset(dims, packing, width, height, 97 format, type, 98 0, 0, 0); 99 uint32_t last_pixel = _mesa_image_offset(dims, packing, width, height, 100 format, type, 101 depth-1, height-1, width); 102 row_stride = _mesa_image_row_stride(packing, width, format, type); 103 104 if (_mesa_is_bufferobj(packing->BufferObj)) { 105 *tmp_pbo = NULL; 106 buffer_obj = packing->BufferObj; 107 first_pixel += (intptr_t)pixels; 108 } else { 109 bool is_pixel_pack = pbo_target == GL_PIXEL_PACK_BUFFER; 110 111 assert(create_pbo); 112 113 *tmp_pbo = ctx->Driver.NewBufferObject(ctx, 0xDEADBEEF); 114 if (*tmp_pbo == NULL) 115 return NULL; 116 117 /* In case of GL_PIXEL_PACK_BUFFER, pass null pointer for the pixel 118 * data to avoid unnecessary data copying in _mesa_buffer_data. 119 */ 120 if (is_pixel_pack) 121 _mesa_buffer_data(ctx, *tmp_pbo, GL_NONE, 122 last_pixel - first_pixel, 123 NULL, 124 GL_STREAM_READ, 125 __func__); 126 else 127 _mesa_buffer_data(ctx, *tmp_pbo, GL_NONE, 128 last_pixel - first_pixel, 129 (char *)pixels + first_pixel, 130 GL_STREAM_DRAW, 131 __func__); 132 133 buffer_obj = *tmp_pbo; 134 first_pixel = 0; 135 } 136 137 _mesa_GenTextures(1, tmp_tex); 138 tex_obj = _mesa_lookup_texture(ctx, *tmp_tex); 139 _mesa_initialize_texture_object(ctx, tex_obj, *tmp_tex, GL_TEXTURE_2D); 140 /* This must be set after _mesa_initialize_texture_object, not before. */ 141 tex_obj->Immutable = GL_TRUE; 142 /* This is required for interactions with ARB_texture_view. */ 143 tex_obj->NumLayers = 1; 144 145 internal_format = _mesa_get_format_base_format(pbo_format); 146 147 /* The texture is addressed as a single very-tall image, so we 148 * need to pack the multiple image depths together taking the 149 * inter-image padding into account. 150 */ 151 int image_height = packing->ImageHeight == 0 ? height : packing->ImageHeight; 152 int full_height = image_height * (depth - 1) + height; 153 154 tex_image = _mesa_get_tex_image(ctx, tex_obj, tex_obj->Target, 0); 155 _mesa_init_teximage_fields(ctx, tex_image, width, full_height, 1, 156 0, internal_format, pbo_format); 157 158 read_only = pbo_target == GL_PIXEL_UNPACK_BUFFER; 159 if (!ctx->Driver.SetTextureStorageForBufferObject(ctx, tex_obj, 160 buffer_obj, 161 first_pixel, 162 row_stride, 163 read_only)) { 164 _mesa_DeleteTextures(1, tmp_tex); 165 _mesa_reference_buffer_object(ctx, tmp_pbo, NULL); 166 return NULL; 167 } 168 169 return tex_image; 170} 171 172bool 173_mesa_meta_pbo_TexSubImage(struct gl_context *ctx, GLuint dims, 174 struct gl_texture_image *tex_image, 175 int xoffset, int yoffset, int zoffset, 176 int width, int height, int depth, 177 GLenum format, GLenum type, const void *pixels, 178 bool allocate_storage, bool create_pbo, 179 const struct gl_pixelstore_attrib *packing) 180{ 181 struct gl_buffer_object *pbo = NULL; 182 GLuint pbo_tex = 0; 183 struct gl_framebuffer *readFb = NULL; 184 struct gl_framebuffer *drawFb = NULL; 185 int image_height; 186 struct gl_texture_image *pbo_tex_image; 187 GLenum status; 188 bool success = false; 189 int z; 190 191 if (!_mesa_is_bufferobj(packing->BufferObj) && 192 (!create_pbo || pixels == NULL)) 193 return false; 194 195 if (format == GL_DEPTH_COMPONENT || 196 format == GL_DEPTH_STENCIL || 197 format == GL_STENCIL_INDEX || 198 format == GL_COLOR_INDEX) 199 return false; 200 201 if (ctx->_ImageTransferState) 202 return false; 203 204 /* This function rely on BlitFramebuffer to fill in the pixel data for 205 * glTex[Sub]Image*D. But, BlitFrameBuffer doesn't support signed to 206 * unsigned or unsigned to signed integer conversions. 207 */ 208 if (need_signed_unsigned_int_conversion(tex_image->TexFormat, format, type)) 209 return false; 210 211 /* For arrays, use a tall (height * depth) 2D texture but taking into 212 * account the inter-image padding specified with the image height packing 213 * property. 214 */ 215 image_height = packing->ImageHeight == 0 ? height : packing->ImageHeight; 216 217 pbo_tex_image = create_texture_for_pbo(ctx, create_pbo, 218 GL_PIXEL_UNPACK_BUFFER, 219 dims, width, height, depth, 220 format, type, pixels, packing, 221 &pbo, &pbo_tex); 222 if (!pbo_tex_image) 223 return false; 224 225 if (allocate_storage) 226 ctx->Driver.AllocTextureImageBuffer(ctx, tex_image); 227 228 _mesa_meta_begin(ctx, ~(MESA_META_PIXEL_TRANSFER | 229 MESA_META_PIXEL_STORE)); 230 231 readFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF); 232 if (readFb == NULL) 233 goto fail; 234 235 drawFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF); 236 if (drawFb == NULL) 237 goto fail; 238 239 _mesa_bind_framebuffers(ctx, drawFb, tex_image ? readFb : ctx->ReadBuffer); 240 241 if (tex_image->TexObject->Target == GL_TEXTURE_1D_ARRAY) { 242 assert(depth == 1); 243 assert(zoffset == 0); 244 depth = height; 245 height = 1; 246 image_height = 1; 247 zoffset = yoffset; 248 yoffset = 0; 249 } 250 251 _mesa_meta_framebuffer_texture_image(ctx, ctx->ReadBuffer, 252 GL_COLOR_ATTACHMENT0, 253 pbo_tex_image, 0); 254 /* If this passes on the first layer it should pass on the others */ 255 status = _mesa_check_framebuffer_status(ctx, ctx->ReadBuffer); 256 if (status != GL_FRAMEBUFFER_COMPLETE) 257 goto fail; 258 259 _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer, 260 GL_COLOR_ATTACHMENT0, 261 tex_image, zoffset); 262 /* If this passes on the first layer it should pass on the others */ 263 status = _mesa_check_framebuffer_status(ctx, ctx->DrawBuffer); 264 if (status != GL_FRAMEBUFFER_COMPLETE) 265 goto fail; 266 267 _mesa_update_state(ctx); 268 269 if (_mesa_meta_BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer, 270 0, 0, width, height, 271 xoffset, yoffset, 272 xoffset + width, yoffset + height, 273 GL_COLOR_BUFFER_BIT, GL_NEAREST)) 274 goto fail; 275 276 for (z = 1; z < depth; z++) { 277 _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer, 278 GL_COLOR_ATTACHMENT0, 279 tex_image, zoffset + z); 280 281 _mesa_update_state(ctx); 282 283 _mesa_meta_BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer, 284 0, z * image_height, 285 width, z * image_height + height, 286 xoffset, yoffset, 287 xoffset + width, yoffset + height, 288 GL_COLOR_BUFFER_BIT, GL_NEAREST); 289 } 290 291 success = true; 292 293fail: 294 _mesa_reference_framebuffer(&readFb, NULL); 295 _mesa_reference_framebuffer(&drawFb, NULL); 296 _mesa_DeleteTextures(1, &pbo_tex); 297 _mesa_reference_buffer_object(ctx, &pbo, NULL); 298 299 _mesa_meta_end(ctx); 300 301 return success; 302} 303 304bool 305_mesa_meta_pbo_GetTexSubImage(struct gl_context *ctx, GLuint dims, 306 struct gl_texture_image *tex_image, 307 int xoffset, int yoffset, int zoffset, 308 int width, int height, int depth, 309 GLenum format, GLenum type, const void *pixels, 310 const struct gl_pixelstore_attrib *packing) 311{ 312 struct gl_buffer_object *pbo = NULL; 313 GLuint pbo_tex = 0; 314 struct gl_framebuffer *readFb; 315 struct gl_framebuffer *drawFb; 316 int image_height; 317 struct gl_texture_image *pbo_tex_image; 318 struct gl_renderbuffer *rb = NULL; 319 GLenum dstBaseFormat = _mesa_unpack_format_to_base_format(format); 320 GLenum status, src_base_format; 321 bool success = false, clear_channels_to_zero = false; 322 float save_clear_color[4]; 323 int z; 324 325 if (!_mesa_is_bufferobj(packing->BufferObj)) 326 return false; 327 328 if (format == GL_DEPTH_COMPONENT || 329 format == GL_DEPTH_STENCIL || 330 format == GL_STENCIL_INDEX || 331 format == GL_COLOR_INDEX) 332 return false; 333 334 /* Don't use meta path for readpixels in below conditions. */ 335 if (!tex_image) { 336 rb = ctx->ReadBuffer->_ColorReadBuffer; 337 338 /* _mesa_get_readpixels_transfer_ops() includes the cases of read 339 * color clamping along with the ctx->_ImageTransferState. 340 */ 341 if (_mesa_get_readpixels_transfer_ops(ctx, rb->Format, format, 342 type, GL_FALSE)) 343 return false; 344 345 if (_mesa_need_rgb_to_luminance_conversion(rb->_BaseFormat, 346 dstBaseFormat)) 347 return false; 348 349 /* This function rely on BlitFramebuffer to fill in the pixel data for 350 * ReadPixels. But, BlitFrameBuffer doesn't support signed to unsigned 351 * or unsigned to signed integer conversions. OpenGL spec expects an 352 * invalid operation in that case. 353 */ 354 if (need_signed_unsigned_int_conversion(rb->Format, format, type)) 355 return false; 356 } 357 358 /* For arrays, use a tall (height * depth) 2D texture but taking into 359 * account the inter-image padding specified with the image height packing 360 * property. 361 */ 362 image_height = packing->ImageHeight == 0 ? height : packing->ImageHeight; 363 364 pbo_tex_image = create_texture_for_pbo(ctx, false, GL_PIXEL_PACK_BUFFER, 365 dims, width, height, depth, 366 format, type, pixels, packing, 367 &pbo, &pbo_tex); 368 if (!pbo_tex_image) 369 return false; 370 371 _mesa_meta_begin(ctx, ~(MESA_META_PIXEL_TRANSFER | 372 MESA_META_PIXEL_STORE)); 373 374 /* GL_CLAMP_FRAGMENT_COLOR doesn't affect ReadPixels and GettexImage */ 375 if (ctx->Extensions.ARB_color_buffer_float) 376 _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE); 377 378 readFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF); 379 if (readFb == NULL) 380 goto fail; 381 382 drawFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF); 383 if (drawFb == NULL) 384 goto fail; 385 386 if (tex_image && tex_image->TexObject->Target == GL_TEXTURE_1D_ARRAY) { 387 assert(depth == 1); 388 assert(zoffset == 0); 389 depth = height; 390 height = 1; 391 image_height = 1; 392 zoffset = yoffset; 393 yoffset = 0; 394 } 395 396 /* If we were given a texture, bind it to the read framebuffer. If not, 397 * we're doing a ReadPixels and we should just use whatever framebuffer 398 * the client has bound. 399 */ 400 _mesa_bind_framebuffers(ctx, drawFb, tex_image ? readFb : ctx->ReadBuffer); 401 if (tex_image) { 402 _mesa_meta_framebuffer_texture_image(ctx, ctx->ReadBuffer, 403 GL_COLOR_ATTACHMENT0, 404 tex_image, zoffset); 405 /* If this passes on the first layer it should pass on the others */ 406 status = _mesa_check_framebuffer_status(ctx, ctx->ReadBuffer); 407 if (status != GL_FRAMEBUFFER_COMPLETE) 408 goto fail; 409 } else { 410 assert(depth == 1); 411 } 412 413 _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer, 414 GL_COLOR_ATTACHMENT0, 415 pbo_tex_image, 0); 416 /* If this passes on the first layer it should pass on the others */ 417 status = _mesa_check_framebuffer_status(ctx, ctx->DrawBuffer); 418 if (status != GL_FRAMEBUFFER_COMPLETE) 419 goto fail; 420 421 _mesa_update_state(ctx); 422 423 if (_mesa_meta_BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer, 424 xoffset, yoffset, 425 xoffset + width, yoffset + height, 426 0, 0, width, height, 427 GL_COLOR_BUFFER_BIT, GL_NEAREST)) 428 goto fail; 429 430 src_base_format = tex_image ? 431 tex_image->_BaseFormat : 432 ctx->ReadBuffer->_ColorReadBuffer->_BaseFormat; 433 434 /* Depending on the base formats involved we might need to rebase some 435 * values. For example if we download from a Luminance format to RGBA 436 * format, we want G=0 and B=0. 437 */ 438 clear_channels_to_zero = 439 _mesa_need_luminance_to_rgb_conversion(src_base_format, 440 pbo_tex_image->_BaseFormat); 441 442 if (clear_channels_to_zero) { 443 memcpy(save_clear_color, ctx->Color.ClearColor.f, 4 * sizeof(float)); 444 /* Clear the Green, Blue channels. */ 445 _mesa_ColorMask(GL_FALSE, GL_TRUE, GL_TRUE, 446 src_base_format != GL_LUMINANCE_ALPHA); 447 _mesa_ClearColor(0.0, 0.0, 0.0, 1.0); 448 _mesa_Clear(GL_COLOR_BUFFER_BIT); 449 } 450 451 for (z = 1; z < depth; z++) { 452 _mesa_meta_framebuffer_texture_image(ctx, ctx->ReadBuffer, 453 GL_COLOR_ATTACHMENT0, 454 tex_image, zoffset + z); 455 456 _mesa_update_state(ctx); 457 458 _mesa_meta_BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer, 459 xoffset, yoffset, 460 xoffset + width, yoffset + height, 461 0, z * image_height, 462 width, z * image_height + height, 463 GL_COLOR_BUFFER_BIT, GL_NEAREST); 464 if (clear_channels_to_zero) 465 _mesa_Clear(GL_COLOR_BUFFER_BIT); 466 } 467 468 /* Unmask the color channels and restore the saved clear color values. */ 469 if (clear_channels_to_zero) { 470 _mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 471 _mesa_ClearColor(save_clear_color[0], save_clear_color[1], 472 save_clear_color[2], save_clear_color[3]); 473 } 474 475 success = true; 476 477fail: 478 _mesa_reference_framebuffer(&drawFb, NULL); 479 _mesa_reference_framebuffer(&readFb, NULL); 480 _mesa_DeleteTextures(1, &pbo_tex); 481 _mesa_reference_buffer_object(ctx, &pbo, NULL); 482 483 _mesa_meta_end(ctx); 484 485 return success; 486} 487