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