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