• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**************************************************************************
2  *
3  * Copyright 2007 VMware, Inc.
4  * 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
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  **************************************************************************/
27 
28  /*
29   * Authors:
30   *   Brian Paul
31   */
32 
33 #include "main/errors.h"
34 
35 #include "main/image.h"
36 #include "main/bufferobj.h"
37 #include "main/blit.h"
38 #include "main/format_pack.h"
39 #include "main/framebuffer.h"
40 #include "main/macros.h"
41 #include "main/mtypes.h"
42 #include "main/pack.h"
43 #include "main/pbo.h"
44 #include "main/readpix.h"
45 #include "main/state.h"
46 #include "main/teximage.h"
47 #include "main/texstore.h"
48 #include "main/glformats.h"
49 #include "program/program.h"
50 #include "program/prog_print.h"
51 #include "program/prog_instruction.h"
52 
53 #include "st_atom.h"
54 #include "st_atom_constbuf.h"
55 #include "st_cb_bitmap.h"
56 #include "st_cb_drawpixels.h"
57 #include "st_context.h"
58 #include "st_debug.h"
59 #include "st_draw.h"
60 #include "st_format.h"
61 #include "st_program.h"
62 #include "st_sampler_view.h"
63 #include "st_scissor.h"
64 #include "st_texture.h"
65 #include "st_util.h"
66 #include "st_nir.h"
67 
68 #include "pipe/p_context.h"
69 #include "pipe/p_defines.h"
70 #include "util/format/u_format.h"
71 #include "util/u_inlines.h"
72 #include "util/u_math.h"
73 #include "util/u_tile.h"
74 #include "cso_cache/cso_context.h"
75 
76 #include "compiler/nir/nir_builder.h"
77 
78 /**
79  * We have a simple glDrawPixels cache to try to optimize the case where the
80  * same image is drawn over and over again.  It basically works as follows:
81  *
82  * 1. After we construct a texture map with the image and draw it, we do
83  *    not discard the texture.  We keep it around, plus we note the
84  *    glDrawPixels width, height, format, etc. parameters and keep a copy
85  *    of the image in a malloc'd buffer.
86  *
87  * 2. On the next glDrawPixels we check if the parameters match the previous
88  *    call.  If those match, we check if the image matches the previous image
89  *    via a memcmp() call.  If everything matches, we re-use the previous
90  *    texture, thereby avoiding the cost creating a new texture and copying
91  *    the image to it.
92  *
93  * The effectiveness of this cache depends upon:
94  * 1. If the memcmp() finds a difference, it happens relatively quickly.
95       Hopefully, not just the last pixels differ!
96  * 2. If the memcmp() finds no difference, doing that check is faster than
97  *    creating and loading a texture.
98  *
99  * Notes:
100  * 1. We don't support any pixel unpacking parameters.
101  * 2. We don't try to cache images in Pixel Buffer Objects.
102  * 3. Instead of saving the whole image, perhaps some sort of reliable
103  *    checksum function could be used instead.
104  */
105 #define USE_DRAWPIXELS_CACHE 1
106 
107 static nir_def *
sample_via_nir(nir_builder * b,const char * name,int sampler,nir_alu_type alu_type)108 sample_via_nir(nir_builder *b,  const char *name, int sampler,
109                nir_alu_type alu_type)
110 {
111    nir_def *baryc = nir_load_barycentric_pixel(b, 32,
112                                                .interp_mode = INTERP_MODE_SMOOTH);
113    nir_def *texcoord =
114       nir_load_interpolated_input(b, 2, 32, baryc, nir_imm_int(b, 0),
115                                   .io_semantics.location = VARYING_SLOT_TEX0);
116    const struct glsl_type *sampler2D =
117       glsl_sampler_type(GLSL_SAMPLER_DIM_2D, false, false,
118                         nir_get_glsl_base_type_for_nir_type(alu_type));
119 
120    nir_variable *var =
121       nir_variable_create(b->shader, nir_var_uniform, sampler2D, name);
122    var->data.binding = sampler;
123    var->data.explicit_binding = true;
124 
125    nir_deref_instr *deref = nir_build_deref_var(b, var);
126 
127    nir_tex_instr *tex = nir_tex_instr_create(b->shader, 3);
128    tex->op = nir_texop_tex;
129    tex->sampler_dim = GLSL_SAMPLER_DIM_2D;
130    tex->coord_components = 2;
131    tex->dest_type = alu_type;
132    tex->src[0] = nir_tex_src_for_ssa(nir_tex_src_texture_deref,
133                                      &deref->def);
134    tex->src[1] = nir_tex_src_for_ssa(nir_tex_src_sampler_deref,
135                                      &deref->def);
136    tex->src[2] = nir_tex_src_for_ssa(nir_tex_src_coord, texcoord);
137 
138    nir_def_init(&tex->instr, &tex->def, 4, 32);
139    nir_builder_instr_insert(b, &tex->instr);
140    return nir_channel(b, &tex->def, 0);
141 }
142 
143 static void *
make_drawpix_z_stencil_program_nir(struct st_context * st,bool write_depth,bool write_stencil)144 make_drawpix_z_stencil_program_nir(struct st_context *st,
145                                    bool write_depth,
146                                    bool write_stencil)
147 {
148    const nir_shader_compiler_options *options =
149       st_get_nir_compiler_options(st, MESA_SHADER_FRAGMENT);
150 
151    nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_FRAGMENT, options,
152                                                   "drawpixels %s%s",
153                                                   write_depth ? "Z" : "",
154                                                   write_stencil ? "S" : "");
155    b.shader->info.io_lowered = true;
156 
157    if (write_depth) {
158       nir_def *depth = sample_via_nir(&b, "depth", 0, nir_type_float32);
159       nir_store_output(&b, nir_channel(&b, depth, 0), nir_imm_int(&b, 0),
160                        .io_semantics.location = FRAG_RESULT_DEPTH);
161 
162       /* Also copy color */
163       nir_def *baryc = nir_load_barycentric_pixel(&b, 32);
164       nir_def *color = nir_load_interpolated_input(&b, 4, 32, baryc,
165                                                    nir_imm_int(&b, 0),
166                                                    .io_semantics.location = VARYING_SLOT_COL0);
167       nir_store_output(&b, color, nir_imm_int(&b, 0),
168                        .io_semantics.location = FRAG_RESULT_COLOR);
169    }
170 
171    if (write_stencil) {
172       nir_def *stencil = sample_via_nir(&b, "stencil", 1, nir_type_uint32);
173       nir_store_output(&b, nir_channel(&b, stencil, 0), nir_imm_int(&b, 0),
174                        .src_type = nir_type_int32,
175                        .io_semantics.location = FRAG_RESULT_STENCIL);
176    }
177 
178    return st_nir_finish_builtin_shader(st, b.shader);
179 }
180 
181 static void *
make_drawpix_zs_to_color_program_nir(struct st_context * st,bool rgba)182 make_drawpix_zs_to_color_program_nir(struct st_context *st,
183                                    bool rgba)
184 {
185    const nir_shader_compiler_options *options =
186       st_get_nir_compiler_options(st, MESA_SHADER_FRAGMENT);
187 
188    nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_FRAGMENT, options,
189                                                   "copypixels ZStoC");
190    b.shader->info.io_lowered = true;
191 
192    /* Sample depth and stencil */
193    nir_def *depth = sample_via_nir(&b, "depth", 0, nir_type_float32);
194    nir_def *stencil = sample_via_nir(&b, "stencil", 1, nir_type_uint32);
195 
196    nir_def *shifted_depth = nir_fmul(&b,nir_f2f64(&b, depth), nir_imm_double(&b,0xffffff));
197    nir_def *int_depth = nir_f2u32(&b,shifted_depth);
198 
199    nir_def *ds[4];
200    ds[0] = nir_ubitfield_extract(&b, stencil, nir_imm_int(&b, 0), nir_imm_int(&b,8));
201    ds[1] = nir_ubitfield_extract(&b, int_depth, nir_imm_int(&b, 0), nir_imm_int(&b,8));
202    ds[2] = nir_ubitfield_extract(&b, int_depth, nir_imm_int(&b, 8), nir_imm_int(&b,8));
203    ds[3] = nir_ubitfield_extract(&b, int_depth, nir_imm_int(&b, 16), nir_imm_int(&b,8));
204 
205    nir_def *ds_comp[4];
206    ds_comp[0] = nir_fsat(&b, nir_fmul_imm(&b, nir_u2f32(&b, ds[3]), 1.0/255.0));
207    ds_comp[1] = nir_fsat(&b, nir_fmul_imm(&b, nir_u2f32(&b, ds[2]), 1.0/255.0));
208    ds_comp[2] = nir_fsat(&b, nir_fmul_imm(&b, nir_u2f32(&b, ds[1]), 1.0/255.0));
209    ds_comp[3] = nir_fsat(&b, nir_fmul_imm(&b, nir_u2f32(&b, ds[0]), 1.0/255.0));
210 
211    nir_def *unpacked_ds = nir_vec4(&b, ds_comp[0], ds_comp[1], ds_comp[2], ds_comp[3]);
212 
213    if (!rgba) {
214       /* ZS -> BGRA blit */
215       unsigned zyxw[4] = { 2, 1, 0, 3 };
216       unpacked_ds = nir_swizzle(&b, unpacked_ds, zyxw, 4);
217    }
218 
219    nir_store_output(&b, unpacked_ds, nir_imm_int(&b, 0),
220                     .io_semantics.location = FRAG_RESULT_COLOR);
221 
222    return st_nir_finish_builtin_shader(st, b.shader);
223 }
224 
225 
226 /**
227  * Create fragment program that does a TEX() instruction to get a Z and/or
228  * stencil value value, then writes to FRAG_RESULT_DEPTH/FRAG_RESULT_STENCIL.
229  * Used for glDrawPixels(GL_DEPTH_COMPONENT / GL_STENCIL_INDEX).
230  * Pass fragment color through as-is.
231  *
232  * \return CSO of the fragment shader.
233  */
234 static void *
get_drawpix_z_stencil_program(struct st_context * st,bool write_depth,bool write_stencil)235 get_drawpix_z_stencil_program(struct st_context *st,
236                               bool write_depth,
237                               bool write_stencil)
238 {
239    const GLuint shaderIndex = write_depth * 2 + write_stencil;
240    void *cso;
241 
242    assert(shaderIndex < ARRAY_SIZE(st->drawpix.zs_shaders));
243 
244    if (st->drawpix.zs_shaders[shaderIndex]) {
245       /* already have the proper shader */
246       return st->drawpix.zs_shaders[shaderIndex];
247    }
248 
249    cso = make_drawpix_z_stencil_program_nir(st, write_depth, write_stencil);
250 
251    /* save the new shader */
252    st->drawpix.zs_shaders[shaderIndex] = cso;
253    return cso;
254 }
255 
256 /**
257  * Create fragment program that does a TEX() instruction to get a Z and
258  * stencil value value, then writes to FRAG_RESULT_COLOR.
259  * Used for glCopyPixels(GL_DEPTH_STENCIL_TO_RGBA_NV / GL_DEPTH_STENCIL_TO_BGRA_NV).
260  *
261  * \return CSO of the fragment shader.
262  */
263 static void *
get_drawpix_zs_to_color_program(struct st_context * st,bool rgba)264 get_drawpix_zs_to_color_program(struct st_context *st,
265                               bool rgba)
266 {
267    void *cso;
268    GLuint shaderIndex;
269 
270    if (rgba)
271       shaderIndex = 4;
272    else
273       shaderIndex = 5;
274 
275    assert(shaderIndex < ARRAY_SIZE(st->drawpix.zs_shaders));
276 
277    if (st->drawpix.zs_shaders[shaderIndex]) {
278       /* already have the proper shader */
279       return st->drawpix.zs_shaders[shaderIndex];
280    }
281 
282    cso = make_drawpix_zs_to_color_program_nir(st, rgba);
283 
284    /* save the new shader */
285    st->drawpix.zs_shaders[shaderIndex] = cso;
286    return cso;
287 }
288 
289 /**
290  * Create a simple vertex shader that just passes through the
291  * vertex position, texcoord, and color.
292  */
293 void
st_make_passthrough_vertex_shader(struct st_context * st)294 st_make_passthrough_vertex_shader(struct st_context *st)
295 {
296    if (st->passthrough_vs)
297       return;
298 
299    unsigned inputs[] =
300       {  VERT_ATTRIB_POS, VERT_ATTRIB_COLOR0, VERT_ATTRIB_GENERIC0 };
301    gl_varying_slot outputs[] =
302       { VARYING_SLOT_POS,  VARYING_SLOT_COL0,    VARYING_SLOT_TEX0 };
303 
304    st->passthrough_vs =
305       st_nir_make_passthrough_vs(st, "drawpixels VS", 3, inputs, outputs, 0);
306 }
307 
308 
309 /**
310  * Return a texture internalFormat for drawing/copying an image
311  * of the given format and type.
312  */
313 static GLenum
internal_format(struct gl_context * ctx,GLenum format,GLenum type)314 internal_format(struct gl_context *ctx, GLenum format, GLenum type)
315 {
316    switch (format) {
317    case GL_DEPTH_COMPONENT:
318       switch (type) {
319       case GL_UNSIGNED_SHORT:
320          return GL_DEPTH_COMPONENT16;
321 
322       case GL_UNSIGNED_INT:
323          return GL_DEPTH_COMPONENT32;
324 
325       case GL_FLOAT:
326          if (ctx->Extensions.ARB_depth_buffer_float)
327             return GL_DEPTH_COMPONENT32F;
328          else
329             return GL_DEPTH_COMPONENT;
330 
331       default:
332          return GL_DEPTH_COMPONENT;
333       }
334 
335    case GL_DEPTH_STENCIL:
336       switch (type) {
337       case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
338          return GL_DEPTH32F_STENCIL8;
339 
340       case GL_UNSIGNED_INT_24_8:
341       default:
342          return GL_DEPTH24_STENCIL8;
343       }
344 
345    case GL_STENCIL_INDEX:
346       return GL_STENCIL_INDEX;
347 
348    default:
349       if (_mesa_is_enum_format_integer(format)) {
350          switch (type) {
351          case GL_BYTE:
352             return GL_RGBA8I;
353          case GL_UNSIGNED_BYTE:
354             return GL_RGBA8UI;
355          case GL_SHORT:
356             return GL_RGBA16I;
357          case GL_UNSIGNED_SHORT:
358             return GL_RGBA16UI;
359          case GL_INT:
360             return GL_RGBA32I;
361          case GL_UNSIGNED_INT:
362             return GL_RGBA32UI;
363          default:
364             assert(0 && "Unexpected type in internal_format()");
365             return GL_RGBA_INTEGER;
366          }
367       }
368       else {
369          switch (type) {
370          case GL_UNSIGNED_BYTE:
371          case GL_UNSIGNED_INT_8_8_8_8:
372          case GL_UNSIGNED_INT_8_8_8_8_REV:
373          default:
374             return GL_RGBA8;
375 
376          case GL_UNSIGNED_BYTE_3_3_2:
377          case GL_UNSIGNED_BYTE_2_3_3_REV:
378             return GL_R3_G3_B2;
379 
380          case GL_UNSIGNED_SHORT_4_4_4_4:
381          case GL_UNSIGNED_SHORT_4_4_4_4_REV:
382             return GL_RGBA4;
383 
384          case GL_UNSIGNED_SHORT_5_6_5:
385          case GL_UNSIGNED_SHORT_5_6_5_REV:
386             return GL_RGB565;
387 
388          case GL_UNSIGNED_SHORT_5_5_5_1:
389          case GL_UNSIGNED_SHORT_1_5_5_5_REV:
390             return GL_RGB5_A1;
391 
392          case GL_UNSIGNED_INT_10_10_10_2:
393          case GL_UNSIGNED_INT_2_10_10_10_REV:
394             return GL_RGB10_A2;
395 
396          case GL_UNSIGNED_SHORT:
397          case GL_UNSIGNED_INT:
398             return GL_RGBA16;
399 
400          case GL_BYTE:
401             return
402                ctx->Extensions.EXT_texture_snorm ? GL_RGBA8_SNORM : GL_RGBA8;
403 
404          case GL_SHORT:
405          case GL_INT:
406             return
407                ctx->Extensions.EXT_texture_snorm ? GL_RGBA16_SNORM : GL_RGBA16;
408 
409          case GL_HALF_FLOAT_ARB:
410             return
411                ctx->Extensions.ARB_texture_float ? GL_RGBA16F :
412                ctx->Extensions.EXT_texture_snorm ? GL_RGBA16_SNORM : GL_RGBA16;
413 
414          case GL_FLOAT:
415          case GL_DOUBLE:
416             return
417                ctx->Extensions.ARB_texture_float ? GL_RGBA32F :
418                ctx->Extensions.EXT_texture_snorm ? GL_RGBA16_SNORM : GL_RGBA16;
419 
420          case GL_UNSIGNED_INT_5_9_9_9_REV:
421             assert(ctx->Extensions.EXT_texture_shared_exponent);
422             return GL_RGB9_E5;
423 
424          case GL_UNSIGNED_INT_10F_11F_11F_REV:
425             assert(ctx->Extensions.EXT_packed_float);
426             return GL_R11F_G11F_B10F;
427          }
428       }
429    }
430 }
431 
432 
433 /**
434  * Create a temporary texture to hold an image of the given size.
435  * If width, height are not POT and the driver only handles POT textures,
436  * allocate the next larger size of texture that is POT.
437  */
438 static struct pipe_resource *
alloc_texture(struct st_context * st,GLsizei width,GLsizei height,enum pipe_format texFormat,unsigned bind)439 alloc_texture(struct st_context *st, GLsizei width, GLsizei height,
440               enum pipe_format texFormat, unsigned bind)
441 {
442    struct pipe_resource *pt;
443 
444    pt = st_texture_create(st, st->internal_target, texFormat, 0,
445                           width, height, 1, 1, 0, bind, false,
446                           PIPE_COMPRESSION_FIXED_RATE_NONE);
447 
448    return pt;
449 }
450 
451 
452 /**
453  * Search the cache for an image which matches the given parameters.
454  * \return  pipe_resource pointer if found, NULL if not found.
455  */
456 static struct pipe_resource *
search_drawpixels_cache(struct st_context * st,GLsizei width,GLsizei height,GLenum format,GLenum type,const struct gl_pixelstore_attrib * unpack,const void * pixels)457 search_drawpixels_cache(struct st_context *st,
458                         GLsizei width, GLsizei height,
459                         GLenum format, GLenum type,
460                         const struct gl_pixelstore_attrib *unpack,
461                         const void *pixels)
462 {
463    struct pipe_resource *pt = NULL;
464    const GLint bpp = _mesa_bytes_per_pixel(format, type);
465    unsigned i;
466 
467    if ((unpack->RowLength != 0 && unpack->RowLength != width) ||
468        unpack->SkipPixels != 0 ||
469        unpack->SkipRows != 0 ||
470        unpack->SwapBytes ||
471        unpack->BufferObj) {
472       /* we don't allow non-default pixel unpacking values */
473       return NULL;
474    }
475 
476    /* Search cache entries for a match */
477    for (i = 0; i < ARRAY_SIZE(st->drawpix_cache.entries); i++) {
478       struct drawpix_cache_entry *entry = &st->drawpix_cache.entries[i];
479 
480       if (width == entry->width &&
481           height == entry->height &&
482           format == entry->format &&
483           type == entry->type &&
484           pixels == entry->user_pointer &&
485           entry->image) {
486          assert(entry->texture);
487 
488          /* check if the pixel data is the same */
489          if (memcmp(pixels, entry->image, width * height * bpp) == 0) {
490             /* Success - found a cache match */
491             pipe_resource_reference(&pt, entry->texture);
492             /* refcount of returned texture should be at least two here.  One
493              * reference for the cache to hold on to, one for the caller (which
494              * it will release), and possibly more held by the driver.
495              */
496             assert(pt->reference.count >= 2);
497 
498             /* update the age of this entry */
499             entry->age = ++st->drawpix_cache.age;
500 
501             return pt;
502          }
503       }
504    }
505 
506    /* no cache match found */
507    return NULL;
508 }
509 
510 
511 /**
512  * Find the oldest entry in the glDrawPixels cache.  We'll replace this
513  * one when we need to store a new image.
514  */
515 static struct drawpix_cache_entry *
find_oldest_drawpixels_cache_entry(struct st_context * st)516 find_oldest_drawpixels_cache_entry(struct st_context *st)
517 {
518    unsigned oldest_age = ~0u, oldest_index = ~0u;
519    unsigned i;
520 
521    /* Find entry with oldest (lowest) age */
522    for (i = 0; i < ARRAY_SIZE(st->drawpix_cache.entries); i++) {
523       const struct drawpix_cache_entry *entry = &st->drawpix_cache.entries[i];
524       if (entry->age < oldest_age) {
525          oldest_age = entry->age;
526          oldest_index = i;
527       }
528    }
529 
530    assert(oldest_index != ~0u);
531 
532    return &st->drawpix_cache.entries[oldest_index];
533 }
534 
535 
536 /**
537  * Try to save the given glDrawPixels image in the cache.
538  */
539 static void
cache_drawpixels_image(struct st_context * st,GLsizei width,GLsizei height,GLenum format,GLenum type,const struct gl_pixelstore_attrib * unpack,const void * pixels,struct pipe_resource * pt)540 cache_drawpixels_image(struct st_context *st,
541                        GLsizei width, GLsizei height,
542                        GLenum format, GLenum type,
543                        const struct gl_pixelstore_attrib *unpack,
544                        const void *pixels,
545                        struct pipe_resource *pt)
546 {
547    if ((unpack->RowLength == 0 || unpack->RowLength == width) &&
548        unpack->SkipPixels == 0 &&
549        unpack->SkipRows == 0) {
550       const GLint bpp = _mesa_bytes_per_pixel(format, type);
551       struct drawpix_cache_entry *entry =
552          find_oldest_drawpixels_cache_entry(st);
553       assert(entry);
554       entry->width = width;
555       entry->height = height;
556       entry->format = format;
557       entry->type = type;
558       entry->user_pointer = pixels;
559       free(entry->image);
560       entry->image = malloc(width * height * bpp);
561       if (entry->image) {
562          memcpy(entry->image, pixels, width * height * bpp);
563          pipe_resource_reference(&entry->texture, pt);
564          entry->age = ++st->drawpix_cache.age;
565       }
566       else {
567          /* out of memory, free/disable cached texture */
568          entry->width = 0;
569          entry->height = 0;
570          pipe_resource_reference(&entry->texture, NULL);
571       }
572    }
573 }
574 
575 
576 /**
577  * Make texture containing an image for glDrawPixels image.
578  * If 'pixels' is NULL, leave the texture image data undefined.
579  */
580 static struct pipe_resource *
make_texture(struct st_context * st,GLsizei width,GLsizei height,GLenum format,GLenum type,const struct gl_pixelstore_attrib * unpack,const void * pixels)581 make_texture(struct st_context *st,
582 	     GLsizei width, GLsizei height, GLenum format, GLenum type,
583 	     const struct gl_pixelstore_attrib *unpack,
584 	     const void *pixels)
585 {
586    struct gl_context *ctx = st->ctx;
587    struct pipe_context *pipe = st->pipe;
588    mesa_format mformat;
589    struct pipe_resource *pt = NULL;
590    enum pipe_format pipeFormat;
591    GLenum baseInternalFormat;
592 
593 #if USE_DRAWPIXELS_CACHE
594    pt = search_drawpixels_cache(st, width, height, format, type,
595                                 unpack, pixels);
596    if (pt) {
597       return pt;
598    }
599 #endif
600 
601    /* Choose a pixel format for the temp texture which will hold the
602     * image to draw.
603     */
604    pipeFormat = st_choose_matching_format(st, PIPE_BIND_SAMPLER_VIEW,
605                                           format, type, unpack->SwapBytes);
606 
607    if (pipeFormat == PIPE_FORMAT_NONE) {
608       /* Use the generic approach. */
609       GLenum intFormat = internal_format(ctx, format, type);
610 
611       pipeFormat = st_choose_format(st, intFormat, format, type,
612                                     st->internal_target, 0, 0,
613                                     PIPE_BIND_SAMPLER_VIEW,
614                                     false, false);
615       assert(pipeFormat != PIPE_FORMAT_NONE);
616    }
617 
618    mformat = st_pipe_format_to_mesa_format(pipeFormat);
619    baseInternalFormat = _mesa_get_format_base_format(mformat);
620 
621    pixels = _mesa_map_pbo_source(ctx, unpack, pixels);
622    if (!pixels)
623       return NULL;
624 
625    /* alloc temporary texture */
626    pt = alloc_texture(st, width, height, pipeFormat, PIPE_BIND_SAMPLER_VIEW);
627    if (!pt) {
628       _mesa_unmap_pbo_source(ctx, unpack);
629       return NULL;
630    }
631 
632    {
633       struct pipe_transfer *transfer;
634       GLubyte *dest;
635       const GLbitfield imageTransferStateSave = ctx->_ImageTransferState;
636 
637       /* we'll do pixel transfer in a fragment shader */
638       ctx->_ImageTransferState = 0x0;
639 
640       /* map texture transfer */
641       dest = pipe_texture_map(pipe, pt, 0, 0,
642                               PIPE_MAP_WRITE | PIPE_MAP_DISCARD_WHOLE_RESOURCE,
643                               0, 0, width, height, &transfer);
644       if (!dest) {
645          pipe_resource_reference(&pt, NULL);
646          _mesa_unmap_pbo_source(ctx, unpack);
647          return NULL;
648       }
649 
650       /* Put image into texture transfer.
651        * Note that the image is actually going to be upside down in
652        * the texture.  We deal with that with texcoords.
653        */
654       if ((format == GL_RGBA || format == GL_BGRA)
655           && type == GL_UNSIGNED_BYTE) {
656          /* Use a memcpy-based texstore to avoid software pixel swizzling.
657           * We'll do the necessary swizzling with the pipe_sampler_view to
658           * give much better performance.
659           * XXX in the future, expand this to accomodate more format and
660           * type combinations.
661           */
662          _mesa_memcpy_texture(ctx, 2,
663                               mformat,          /* mesa_format */
664                               transfer->stride, /* dstRowStride, bytes */
665                               &dest,            /* destSlices */
666                               width, height, 1, /* size */
667                               format, type,     /* src format/type */
668                               pixels,           /* data source */
669                               unpack);
670       }
671       else {
672          ASSERTED bool success;
673          success = _mesa_texstore(ctx, 2,           /* dims */
674                                   baseInternalFormat, /* baseInternalFormat */
675                                   mformat,          /* mesa_format */
676                                   transfer->stride, /* dstRowStride, bytes */
677                                   &dest,            /* destSlices */
678                                   width, height, 1, /* size */
679                                   format, type,     /* src format/type */
680                                   pixels,           /* data source */
681                                   unpack);
682 
683          assert(success);
684       }
685 
686       /* unmap */
687       pipe_texture_unmap(pipe, transfer);
688 
689       /* restore */
690       ctx->_ImageTransferState = imageTransferStateSave;
691    }
692 
693 #if USE_DRAWPIXELS_CACHE
694    cache_drawpixels_image(st, width, height, format, type, unpack, pixels, pt);
695 #endif
696 
697    _mesa_unmap_pbo_source(ctx, unpack);
698 
699    return pt;
700 }
701 
702 
703 static void
draw_textured_quad(struct gl_context * ctx,GLint x,GLint y,GLfloat z,GLsizei width,GLsizei height,GLfloat zoomX,GLfloat zoomY,struct pipe_sampler_view ** sv,int num_sampler_view,void * driver_vp,void * driver_fp,struct st_fp_variant * fpv,const GLfloat * color,GLboolean invertTex,GLboolean write_depth,GLboolean write_stencil)704 draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
705                    GLsizei width, GLsizei height,
706                    GLfloat zoomX, GLfloat zoomY,
707                    struct pipe_sampler_view **sv,
708                    int num_sampler_view,
709                    void *driver_vp,
710                    void *driver_fp,
711                    struct st_fp_variant *fpv,
712                    const GLfloat *color,
713                    GLboolean invertTex,
714                    GLboolean write_depth, GLboolean write_stencil)
715 {
716    struct st_context *st = st_context(ctx);
717    struct pipe_context *pipe = st->pipe;
718    struct cso_context *cso = st->cso_context;
719    const unsigned fb_width = _mesa_geometric_width(ctx->DrawBuffer);
720    const unsigned fb_height = _mesa_geometric_height(ctx->DrawBuffer);
721    GLfloat x0, y0, x1, y1;
722    ASSERTED GLsizei maxSize;
723    bool normalized = sv[0]->texture->target == PIPE_TEXTURE_2D ||
724                      (sv[0]->texture->target == PIPE_TEXTURE_RECT && st->lower_rect_tex);
725    unsigned cso_state_mask;
726 
727    assert(sv[0]->texture->target == st->internal_target);
728 
729    /* limit checks */
730    /* XXX if DrawPixels image is larger than max texture size, break
731     * it up into chunks.
732     */
733    maxSize = st->screen->caps.max_texture_2d_size;
734    assert(width <= maxSize);
735    assert(height <= maxSize);
736 
737    cso_state_mask = (CSO_BIT_RASTERIZER |
738                      CSO_BIT_VIEWPORT |
739                      CSO_BIT_FRAGMENT_SAMPLERS |
740                      CSO_BIT_STREAM_OUTPUTS |
741                      CSO_BIT_VERTEX_ELEMENTS |
742                      CSO_BITS_ALL_SHADERS);
743    if (write_stencil) {
744       cso_state_mask |= (CSO_BIT_DEPTH_STENCIL_ALPHA |
745                          CSO_BIT_BLEND);
746    }
747    cso_save_state(cso, cso_state_mask);
748 
749    /* rasterizer state: just scissor */
750    {
751       struct pipe_rasterizer_state rasterizer;
752       memset(&rasterizer, 0, sizeof(rasterizer));
753       rasterizer.clamp_fragment_color = !st->clamp_frag_color_in_shader &&
754                                         ctx->Color._ClampFragmentColor;
755       rasterizer.half_pixel_center = 1;
756       rasterizer.bottom_edge_rule = 1;
757       rasterizer.depth_clip_near = !ctx->Transform.DepthClampNear;
758       rasterizer.depth_clip_far = !ctx->Transform.DepthClampFar;
759       rasterizer.depth_clamp = !rasterizer.depth_clip_far;
760       rasterizer.scissor = ctx->Scissor.EnableFlags;
761       cso_set_rasterizer(cso, &rasterizer);
762    }
763 
764    if (write_stencil) {
765       /* Stencil writing bypasses the normal fragment pipeline to
766        * disable color writing and set stencil test to always pass.
767        */
768       struct pipe_depth_stencil_alpha_state dsa;
769       struct pipe_blend_state blend;
770 
771       /* depth/stencil */
772       memset(&dsa, 0, sizeof(dsa));
773       dsa.stencil[0].enabled = 1;
774       dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
775       dsa.stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff;
776       dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
777       if (write_depth) {
778          /* writing depth+stencil: depth test always passes */
779          dsa.depth_enabled = 1;
780          dsa.depth_writemask = ctx->Depth.Mask;
781          dsa.depth_func = PIPE_FUNC_ALWAYS;
782       }
783       cso_set_depth_stencil_alpha(cso, &dsa);
784 
785       /* blend (colormask) */
786       memset(&blend, 0, sizeof(blend));
787       cso_set_blend(cso, &blend);
788    }
789 
790    /* fragment shader state: TEX lookup program */
791    cso_set_fragment_shader_handle(cso, driver_fp);
792 
793    /* vertex shader state: position + texcoord pass-through */
794    cso_set_vertex_shader_handle(cso, driver_vp);
795 
796    /* disable other shaders */
797    cso_set_tessctrl_shader_handle(cso, NULL);
798    cso_set_tesseval_shader_handle(cso, NULL);
799    cso_set_geometry_shader_handle(cso, NULL);
800 
801    /* user samplers, plus the drawpix samplers */
802    {
803       struct pipe_sampler_state sampler;
804 
805       memset(&sampler, 0, sizeof(sampler));
806       sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
807       sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
808       sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
809       sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
810       sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
811       sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
812       sampler.unnormalized_coords = !normalized;
813 
814       if (fpv) {
815          /* drawing a color image */
816          const struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
817          uint num = MAX3(fpv->drawpix_sampler + 1,
818                          fpv->pixelmap_sampler + 1,
819                          st->state.num_frag_samplers);
820          uint i;
821 
822          for (i = 0; i < st->state.num_frag_samplers; i++)
823             samplers[i] = &st->state.frag_samplers[i];
824 
825          samplers[fpv->drawpix_sampler] = &sampler;
826          if (sv[1])
827             samplers[fpv->pixelmap_sampler] = &sampler;
828 
829          cso_set_samplers(cso, PIPE_SHADER_FRAGMENT, num, samplers);
830       } else {
831          /* drawing a depth/stencil image */
832          const struct pipe_sampler_state *samplers[2] = {&sampler, &sampler};
833 
834          cso_set_samplers(cso, PIPE_SHADER_FRAGMENT, num_sampler_view, samplers);
835       }
836    }
837 
838    unsigned tex_width = sv[0]->texture->width0;
839    unsigned tex_height = sv[0]->texture->height0;
840 
841    /* user textures, plus the drawpix textures */
842    if (fpv) {
843       /* drawing a color image */
844       struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
845       unsigned num_views =
846          st_get_sampler_views(st, PIPE_SHADER_FRAGMENT,
847                               ctx->FragmentProgram._Current, sampler_views);
848 
849       num_views = MAX3(fpv->drawpix_sampler + 1, fpv->pixelmap_sampler + 1,
850                        num_views);
851 
852       sampler_views[fpv->drawpix_sampler] = sv[0];
853       if (sv[1])
854          sampler_views[fpv->pixelmap_sampler] = sv[1];
855       pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, num_views, 0,
856                               true, sampler_views);
857       st->state.num_sampler_views[PIPE_SHADER_FRAGMENT] = num_views;
858    } else {
859       /* drawing a depth/stencil image */
860       pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, num_sampler_view,
861                               0, false, sv);
862       st->state.num_sampler_views[PIPE_SHADER_FRAGMENT] =
863          MAX2(st->state.num_sampler_views[PIPE_SHADER_FRAGMENT], num_sampler_view);
864 
865       for (unsigned i = 0; i < num_sampler_view; i++)
866          pipe_sampler_view_reference(&sv[i], NULL);
867    }
868 
869    /* viewport state: viewport matching window dims */
870    cso_set_viewport_dims(cso, fb_width, fb_height, true);
871 
872    st->util_velems.count = 3;
873    cso_set_vertex_elements(cso, &st->util_velems);
874    cso_set_stream_outputs(cso, 0, NULL, NULL, 0);
875 
876    /* Compute Gallium window coords (y=0=top) with pixel zoom.
877     * Recall that these coords are transformed by the current
878     * vertex shader and viewport transformation.
879     */
880    if (_mesa_fb_orientation(ctx->DrawBuffer) == Y_0_BOTTOM) {
881       y = fb_height - (int) (y + height * ctx->Pixel.ZoomY);
882       invertTex = !invertTex;
883    }
884 
885    x0 = (GLfloat) x;
886    x1 = x + width * ctx->Pixel.ZoomX;
887    y0 = (GLfloat) y;
888    y1 = y + height * ctx->Pixel.ZoomY;
889 
890    /* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */
891    z = z * 2.0f - 1.0f;
892 
893    {
894       const float clip_x0 = x0 / (float) fb_width * 2.0f - 1.0f;
895       const float clip_y0 = y0 / (float) fb_height * 2.0f - 1.0f;
896       const float clip_x1 = x1 / (float) fb_width * 2.0f - 1.0f;
897       const float clip_y1 = y1 / (float) fb_height * 2.0f - 1.0f;
898       const float maxXcoord = normalized ?
899          ((float) width / tex_width) : (float) width;
900       const float maxYcoord = normalized
901          ? ((float) height / tex_height) : (float) height;
902       const float sLeft = 0.0f, sRight = maxXcoord;
903       const float tTop = invertTex ? maxYcoord : 0.0f;
904       const float tBot = invertTex ? 0.0f : maxYcoord;
905 
906       if (!st_draw_quad(st, clip_x0, clip_y0, clip_x1, clip_y1, z,
907                         sLeft, tBot, sRight, tTop, color, 0)) {
908          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
909       }
910    }
911 
912    /* restore state */
913    /* Unbind all because st/mesa won't do it if the current shader doesn't
914     * use them.
915     */
916    cso_restore_state(cso, CSO_UNBIND_FS_SAMPLERVIEWS);
917    st->state.num_sampler_views[PIPE_SHADER_FRAGMENT] = 0;
918 
919    ctx->Array.NewVertexElements = true;
920    ctx->NewDriverState |= ST_NEW_VERTEX_ARRAYS |
921                           ST_NEW_FS_SAMPLER_VIEWS;
922 }
923 
924 
925 /**
926  * Software fallback to do glDrawPixels(GL_STENCIL_INDEX) when we
927  * can't use a fragment shader to write stencil values.
928  */
929 static void
draw_stencil_pixels(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,const struct gl_pixelstore_attrib * unpack,const void * pixels)930 draw_stencil_pixels(struct gl_context *ctx, GLint x, GLint y,
931                     GLsizei width, GLsizei height, GLenum format, GLenum type,
932                     const struct gl_pixelstore_attrib *unpack,
933                     const void *pixels)
934 {
935    struct st_context *st = st_context(ctx);
936    struct pipe_context *pipe = st->pipe;
937    struct gl_renderbuffer *rb;
938    enum pipe_map_flags usage;
939    struct pipe_transfer *pt;
940    const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
941    uint8_t *stmap;
942    struct gl_pixelstore_attrib clippedUnpack = *unpack;
943    GLubyte *sValues;
944    GLuint *zValues;
945 
946    rb = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
947 
948    if (_mesa_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
949       y = ctx->DrawBuffer->Height - y - height;
950    }
951 
952    if (format == GL_STENCIL_INDEX &&
953        _mesa_is_format_packed_depth_stencil(rb->Format)) {
954       /* writing stencil to a combined depth+stencil buffer */
955       usage = PIPE_MAP_READ_WRITE;
956    }
957    else {
958       usage = PIPE_MAP_WRITE;
959    }
960 
961    stmap = pipe_texture_map(pipe, rb->texture,
962                              rb->surface->u.tex.level,
963                              rb->surface->u.tex.first_layer,
964                              usage, x, y,
965                              width, height, &pt);
966 
967    pixels = _mesa_map_pbo_source(ctx, &clippedUnpack, pixels);
968    assert(pixels);
969 
970    sValues = malloc(width * sizeof(GLubyte));
971    zValues = malloc(width * sizeof(GLuint));
972 
973    if (sValues && zValues) {
974       GLint row;
975       for (row = 0; row < height; row++) {
976          GLfloat *zValuesFloat = (GLfloat*)zValues;
977          GLenum destType = GL_UNSIGNED_BYTE;
978          const void *source = _mesa_image_address2d(&clippedUnpack, pixels,
979                                                       width, height,
980                                                       format, type,
981                                                       row, 0);
982          _mesa_unpack_stencil_span(ctx, width, destType, sValues,
983                                    type, source, &clippedUnpack,
984                                    ctx->_ImageTransferState);
985 
986          if (format == GL_DEPTH_STENCIL) {
987             GLenum ztype =
988                pt->resource->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT ?
989                GL_FLOAT : GL_UNSIGNED_INT;
990 
991             _mesa_unpack_depth_span(ctx, width, ztype, zValues,
992                                     (1 << 24) - 1, type, source,
993                                     &clippedUnpack);
994          }
995 
996          if (zoom) {
997             _mesa_problem(ctx, "Gallium glDrawPixels(GL_STENCIL) with "
998                           "zoom not complete");
999          }
1000 
1001          {
1002             GLint spanY;
1003 
1004             if (_mesa_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
1005                spanY = height - row - 1;
1006             }
1007             else {
1008                spanY = row;
1009             }
1010 
1011             /* now pack the stencil (and Z) values in the dest format */
1012             switch (pt->resource->format) {
1013             case PIPE_FORMAT_S8_UINT:
1014                {
1015                   uint8_t *dest = stmap + spanY * pt->stride;
1016                   assert(usage == PIPE_MAP_WRITE);
1017                   memcpy(dest, sValues, width);
1018                }
1019                break;
1020             case PIPE_FORMAT_Z24_UNORM_S8_UINT:
1021                if (format == GL_DEPTH_STENCIL) {
1022                   uint *dest = (uint *) (stmap + spanY * pt->stride);
1023                   GLint k;
1024                   assert(usage == PIPE_MAP_WRITE);
1025                   for (k = 0; k < width; k++) {
1026                      dest[k] = zValues[k] | (sValues[k] << 24);
1027                   }
1028                }
1029                else {
1030                   uint *dest = (uint *) (stmap + spanY * pt->stride);
1031                   GLint k;
1032                   assert(usage == PIPE_MAP_READ_WRITE);
1033                   for (k = 0; k < width; k++) {
1034                      dest[k] = (dest[k] & 0xffffff) | (sValues[k] << 24);
1035                   }
1036                }
1037                break;
1038             case PIPE_FORMAT_S8_UINT_Z24_UNORM:
1039                if (format == GL_DEPTH_STENCIL) {
1040                   uint *dest = (uint *) (stmap + spanY * pt->stride);
1041                   GLint k;
1042                   assert(usage == PIPE_MAP_WRITE);
1043                   for (k = 0; k < width; k++) {
1044                      dest[k] = (zValues[k] << 8) | (sValues[k] & 0xff);
1045                   }
1046                }
1047                else {
1048                   uint *dest = (uint *) (stmap + spanY * pt->stride);
1049                   GLint k;
1050                   assert(usage == PIPE_MAP_READ_WRITE);
1051                   for (k = 0; k < width; k++) {
1052                      dest[k] = (dest[k] & 0xffffff00) | (sValues[k] & 0xff);
1053                   }
1054                }
1055                break;
1056             case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
1057                if (format == GL_DEPTH_STENCIL) {
1058                   uint *dest = (uint *) (stmap + spanY * pt->stride);
1059                   GLfloat *destf = (GLfloat*)dest;
1060                   GLint k;
1061                   assert(usage == PIPE_MAP_WRITE);
1062                   for (k = 0; k < width; k++) {
1063                      destf[k*2] = zValuesFloat[k];
1064                      dest[k*2+1] = sValues[k] & 0xff;
1065                   }
1066                }
1067                else {
1068                   uint *dest = (uint *) (stmap + spanY * pt->stride);
1069                   GLint k;
1070                   assert(usage == PIPE_MAP_READ_WRITE);
1071                   for (k = 0; k < width; k++) {
1072                      dest[k*2+1] = sValues[k] & 0xff;
1073                   }
1074                }
1075                break;
1076             default:
1077                assert(0);
1078             }
1079          }
1080       }
1081    }
1082    else {
1083       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels()");
1084    }
1085 
1086    free(sValues);
1087    free(zValues);
1088 
1089    _mesa_unmap_pbo_source(ctx, &clippedUnpack);
1090 
1091    /* unmap the stencil buffer */
1092    pipe_texture_unmap(pipe, pt);
1093 }
1094 
1095 
1096 /**
1097  * Get fragment program variant for a glDrawPixels or glCopyPixels
1098  * command for RGBA data.
1099  */
1100 static struct st_fp_variant *
get_color_fp_variant(struct st_context * st)1101 get_color_fp_variant(struct st_context *st)
1102 {
1103    struct gl_context *ctx = st->ctx;
1104    struct st_fp_variant_key key;
1105    struct st_fp_variant *fpv;
1106 
1107    memset(&key, 0, sizeof(key));
1108 
1109    key.st = st->has_shareable_shaders ? NULL : st;
1110    key.drawpixels = 1;
1111    key.scaleAndBias = (ctx->Pixel.RedBias != 0.0 ||
1112                        ctx->Pixel.RedScale != 1.0 ||
1113                        ctx->Pixel.GreenBias != 0.0 ||
1114                        ctx->Pixel.GreenScale != 1.0 ||
1115                        ctx->Pixel.BlueBias != 0.0 ||
1116                        ctx->Pixel.BlueScale != 1.0 ||
1117                        ctx->Pixel.AlphaBias != 0.0 ||
1118                        ctx->Pixel.AlphaScale != 1.0);
1119    key.pixelMaps = ctx->Pixel.MapColorFlag;
1120    key.clamp_color = st->clamp_frag_color_in_shader &&
1121                      ctx->Color._ClampFragmentColor;
1122    key.lower_alpha_func = COMPARE_FUNC_ALWAYS;
1123 
1124    fpv = st_get_fp_variant(st, ctx->FragmentProgram._Current, &key);
1125 
1126    return fpv;
1127 }
1128 
1129 /**
1130  * Get fragment program variant for a glDrawPixels command
1131  * for COLOR_INDEX data
1132  */
1133 static struct st_fp_variant *
get_color_index_fp_variant(struct st_context * st)1134 get_color_index_fp_variant(struct st_context *st)
1135 {
1136    struct gl_context *ctx = st->ctx;
1137    struct st_fp_variant_key key;
1138    struct st_fp_variant *fpv;
1139 
1140    memset(&key, 0, sizeof(key));
1141 
1142    key.st = st->has_shareable_shaders ? NULL : st;
1143    key.drawpixels = 1;
1144    /* Since GL is always in RGBA mode MapColorFlag does not
1145     * affect GL_COLOR_INDEX format.
1146     * Scale and bias also never affect GL_COLOR_INDEX format.
1147     */
1148    key.scaleAndBias = 0;
1149    key.pixelMaps = 0;
1150    key.clamp_color = st->clamp_frag_color_in_shader &&
1151                      ctx->Color._ClampFragmentColor;
1152    key.lower_alpha_func = COMPARE_FUNC_ALWAYS;
1153 
1154    fpv = st_get_fp_variant(st, ctx->FragmentProgram._Current, &key);
1155 
1156    return fpv;
1157 }
1158 
1159 
1160 /**
1161  * Clamp glDrawPixels width and height to the maximum texture size.
1162  */
1163 static void
clamp_size(struct st_context * st,GLsizei * width,GLsizei * height,struct gl_pixelstore_attrib * unpack)1164 clamp_size(struct st_context *st, GLsizei *width, GLsizei *height,
1165            struct gl_pixelstore_attrib *unpack)
1166 {
1167    const int maxSize = st->screen->caps.max_texture_2d_size;
1168 
1169    if (*width > maxSize) {
1170       if (unpack->RowLength == 0)
1171          unpack->RowLength = *width;
1172       *width = maxSize;
1173    }
1174    if (*height > maxSize) {
1175       *height = maxSize;
1176    }
1177 }
1178 
1179 
1180 /**
1181  * Search the array of 4 swizzle components for the named component and return
1182  * its position.
1183  */
1184 static unsigned
search_swizzle(const unsigned char swizzle[4],unsigned component)1185 search_swizzle(const unsigned char swizzle[4], unsigned component)
1186 {
1187    unsigned i;
1188    for (i = 0; i < 4; i++) {
1189       if (swizzle[i] == component)
1190          return i;
1191    }
1192    assert(!"search_swizzle() failed");
1193    return 0;
1194 }
1195 
1196 
1197 /**
1198  * Set the sampler view's swizzle terms.  This is used to handle RGBA
1199  * swizzling when the incoming image format isn't an exact match for
1200  * the actual texture format.  For example, if we have glDrawPixels(
1201  * GL_RGBA, GL_UNSIGNED_BYTE) and we chose the texture format
1202  * PIPE_FORMAT_B8G8R8A8 then we can do use the sampler view swizzle to
1203  * avoid swizzling all the pixels in software in the texstore code.
1204  */
1205 static void
setup_sampler_swizzle(struct pipe_sampler_view * sv,GLenum format,GLenum type)1206 setup_sampler_swizzle(struct pipe_sampler_view *sv, GLenum format, GLenum type)
1207 {
1208    if ((format == GL_RGBA || format == GL_BGRA) && type == GL_UNSIGNED_BYTE) {
1209       const struct util_format_description *desc =
1210          util_format_description(sv->format);
1211       unsigned c0, c1, c2, c3;
1212 
1213       /* Every gallium driver supports at least one 32-bit packed RGBA format.
1214        * We must have chosen one for (GL_RGBA, GL_UNSIGNED_BYTE).
1215        */
1216       assert(desc->block.bits == 32);
1217 
1218       /* invert the format's swizzle to setup the sampler's swizzle */
1219       if (format == GL_RGBA) {
1220          c0 = PIPE_SWIZZLE_X;
1221          c1 = PIPE_SWIZZLE_Y;
1222          c2 = PIPE_SWIZZLE_Z;
1223          c3 = PIPE_SWIZZLE_W;
1224       }
1225       else {
1226          assert(format == GL_BGRA);
1227          c0 = PIPE_SWIZZLE_Z;
1228          c1 = PIPE_SWIZZLE_Y;
1229          c2 = PIPE_SWIZZLE_X;
1230          c3 = PIPE_SWIZZLE_W;
1231       }
1232       sv->swizzle_r = search_swizzle(desc->swizzle, c0);
1233       sv->swizzle_g = search_swizzle(desc->swizzle, c1);
1234       sv->swizzle_b = search_swizzle(desc->swizzle, c2);
1235       sv->swizzle_a = search_swizzle(desc->swizzle, c3);
1236    }
1237    else {
1238       /* use the default sampler swizzle */
1239    }
1240 }
1241 
1242 void
st_DrawPixels(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,const struct gl_pixelstore_attrib * unpack,const void * pixels)1243 st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
1244               GLsizei width, GLsizei height,
1245               GLenum format, GLenum type,
1246               const struct gl_pixelstore_attrib *unpack, const void *pixels)
1247 {
1248    void *driver_fp;
1249    struct st_context *st = st_context(ctx);
1250    GLboolean write_stencil = GL_FALSE, write_depth = GL_FALSE;
1251    struct pipe_sampler_view *sv[2] = { NULL };
1252    int num_sampler_view = 1;
1253    struct gl_pixelstore_attrib clippedUnpack;
1254    struct st_fp_variant *fpv = NULL;
1255    struct pipe_resource *pt;
1256 
1257    /* Mesa state should be up to date by now */
1258    assert(ctx->NewState == 0x0);
1259 
1260    _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer);
1261 
1262    st_flush_bitmap_cache(st);
1263    st_invalidate_readpix_cache(st);
1264 
1265    st_validate_state(st, ST_PIPELINE_META_STATE_MASK);
1266 
1267    clippedUnpack = *unpack;
1268    unpack = &clippedUnpack;
1269 
1270    /* Skip totally clipped DrawPixels. */
1271    if (ctx->Pixel.ZoomX == 1 && ctx->Pixel.ZoomY == 1 &&
1272        !_mesa_clip_drawpixels(ctx, &x, &y, &width, &height, &clippedUnpack))
1273       return;
1274 
1275    /* Limit the size of the glDrawPixels to the max texture size.
1276     * Strictly speaking, that's not correct but since we don't handle
1277     * larger images yet, this is better than crashing.
1278     */
1279    clamp_size(st, &width, &height, &clippedUnpack);
1280 
1281    if (format == GL_DEPTH_STENCIL)
1282       write_stencil = write_depth = GL_TRUE;
1283    else if (format == GL_STENCIL_INDEX)
1284       write_stencil = GL_TRUE;
1285    else if (format == GL_DEPTH_COMPONENT)
1286       write_depth = GL_TRUE;
1287 
1288    if (write_stencil &&
1289        !st->has_stencil_export) {
1290       /* software fallback */
1291       draw_stencil_pixels(ctx, x, y, width, height, format, type,
1292                           unpack, pixels);
1293       return;
1294    }
1295 
1296    /* Put glDrawPixels image into a texture */
1297    pt = make_texture(st, width, height, format, type, unpack, pixels);
1298    if (!pt) {
1299       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
1300       return;
1301    }
1302 
1303    st_make_passthrough_vertex_shader(st);
1304 
1305    /*
1306     * Get vertex/fragment shaders
1307     */
1308    if (write_depth || write_stencil) {
1309       driver_fp = get_drawpix_z_stencil_program(st, write_depth,
1310                                                 write_stencil);
1311    }
1312    else {
1313       fpv = (format != GL_COLOR_INDEX) ? get_color_fp_variant(st) :
1314                                          get_color_index_fp_variant(st);
1315 
1316       driver_fp = fpv->base.driver_shader;
1317 
1318       if (ctx->Pixel.MapColorFlag && format != GL_COLOR_INDEX) {
1319          pipe_sampler_view_reference(&sv[1],
1320                                      st->pixel_xfer.pixelmap_sampler_view);
1321          num_sampler_view++;
1322       }
1323 
1324       /* compiling a new fragment shader variant added new state constants
1325        * into the constant buffer, we need to update them
1326        */
1327       st_upload_constants(st, ctx->FragmentProgram._Current, MESA_SHADER_FRAGMENT);
1328    }
1329 
1330    {
1331       /* create sampler view for the image */
1332       struct pipe_sampler_view templ;
1333 
1334       u_sampler_view_default_template(&templ, pt, pt->format);
1335       /* Set up the sampler view's swizzle */
1336       setup_sampler_swizzle(&templ, format, type);
1337 
1338       sv[0] = st->pipe->create_sampler_view(st->pipe, pt, &templ);
1339    }
1340    if (!sv[0]) {
1341       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
1342       pipe_resource_reference(&pt, NULL);
1343       return;
1344    }
1345 
1346    /* Create a second sampler view to read stencil.  The stencil is
1347     * written using the shader stencil export functionality.
1348     */
1349    if (write_stencil) {
1350       enum pipe_format stencil_format =
1351          util_format_stencil_only(pt->format);
1352       /* we should not be doing pixel map/transfer (see above) */
1353       assert(num_sampler_view == 1);
1354       sv[1] = st_create_texture_sampler_view_format(st->pipe, pt,
1355                                                     stencil_format);
1356       if (!sv[1]) {
1357          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
1358          pipe_resource_reference(&pt, NULL);
1359          pipe_sampler_view_reference(&sv[0], NULL);
1360          return;
1361       }
1362       num_sampler_view++;
1363    }
1364 
1365    draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2],
1366                       width, height,
1367                       ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
1368                       sv,
1369                       num_sampler_view,
1370                       st->passthrough_vs,
1371                       driver_fp, fpv,
1372                       ctx->Current.RasterColor,
1373                       GL_FALSE, write_depth, write_stencil);
1374 
1375    /* free the texture (but may persist in the cache) */
1376    pipe_resource_reference(&pt, NULL);
1377 }
1378 
1379 
1380 
1381 /**
1382  * Software fallback for glCopyPixels(GL_STENCIL).
1383  */
1384 static void
copy_stencil_pixels(struct gl_context * ctx,GLint srcx,GLint srcy,GLsizei width,GLsizei height,GLint dstx,GLint dsty)1385 copy_stencil_pixels(struct gl_context *ctx, GLint srcx, GLint srcy,
1386                     GLsizei width, GLsizei height,
1387                     GLint dstx, GLint dsty)
1388 {
1389    struct gl_renderbuffer *rbDraw;
1390    struct pipe_context *pipe = st_context(ctx)->pipe;
1391    enum pipe_map_flags usage;
1392    struct pipe_transfer *ptDraw;
1393    uint8_t *drawMap;
1394    uint8_t *buffer;
1395    int i;
1396 
1397    buffer = malloc(width * height * sizeof(uint8_t));
1398    if (!buffer) {
1399       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels(stencil)");
1400       return;
1401    }
1402 
1403    /* Get the dest renderbuffer */
1404    rbDraw = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
1405 
1406    /* this will do stencil pixel transfer ops */
1407    _mesa_readpixels(ctx, srcx, srcy, width, height,
1408                     GL_STENCIL_INDEX, GL_UNSIGNED_BYTE,
1409                     &ctx->DefaultPacking, buffer);
1410 
1411    if (0) {
1412       /* debug code: dump stencil values */
1413       GLint row, col;
1414       for (row = 0; row < height; row++) {
1415          printf("%3d: ", row);
1416          for (col = 0; col < width; col++) {
1417             printf("%02x ", buffer[col + row * width]);
1418          }
1419          printf("\n");
1420       }
1421    }
1422 
1423    if (_mesa_is_format_packed_depth_stencil(rbDraw->Format))
1424       usage = PIPE_MAP_READ_WRITE;
1425    else
1426       usage = PIPE_MAP_WRITE;
1427 
1428    if (_mesa_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
1429       dsty = rbDraw->Height - dsty - height;
1430    }
1431 
1432    assert(util_format_get_blockwidth(rbDraw->texture->format) == 1);
1433    assert(util_format_get_blockheight(rbDraw->texture->format) == 1);
1434 
1435    /* map the stencil buffer */
1436    drawMap = pipe_texture_map(pipe,
1437                                rbDraw->texture,
1438                                rbDraw->surface->u.tex.level,
1439                                rbDraw->surface->u.tex.first_layer,
1440                                usage, dstx, dsty,
1441                                width, height, &ptDraw);
1442 
1443    /* draw */
1444    /* XXX PixelZoom not handled yet */
1445    for (i = 0; i < height; i++) {
1446       uint8_t *dst;
1447       const uint8_t *src;
1448       int y;
1449 
1450       y = i;
1451 
1452       if (_mesa_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
1453          y = height - y - 1;
1454       }
1455 
1456       dst = drawMap + y * ptDraw->stride;
1457       src = buffer + i * width;
1458 
1459       _mesa_pack_ubyte_stencil_row(rbDraw->Format, width, src, dst);
1460    }
1461 
1462    free(buffer);
1463 
1464    /* unmap the stencil buffer */
1465    pipe_texture_unmap(pipe, ptDraw);
1466 }
1467 
1468 
1469 /**
1470  * Return renderbuffer to use for reading color pixels for glCopyPixels
1471  */
1472 static struct gl_renderbuffer *
st_get_color_read_renderbuffer(struct gl_context * ctx)1473 st_get_color_read_renderbuffer(struct gl_context *ctx)
1474 {
1475    struct gl_framebuffer *fb = ctx->ReadBuffer;
1476    return fb->_ColorReadBuffer;
1477 }
1478 
1479 
1480 /**
1481  * Try to do a glCopyPixels for simple cases with a blit by calling
1482  * pipe->blit().
1483  *
1484  * We can do this when we're copying color pixels (depth/stencil
1485  * eventually) with no pixel zoom, no pixel transfer ops, no
1486  * per-fragment ops, and the src/dest regions don't overlap.
1487  */
1488 static GLboolean
blit_copy_pixels(struct gl_context * ctx,GLint srcx,GLint srcy,GLsizei width,GLsizei height,GLint dstx,GLint dsty,GLenum type)1489 blit_copy_pixels(struct gl_context *ctx, GLint srcx, GLint srcy,
1490                  GLsizei width, GLsizei height,
1491                  GLint dstx, GLint dsty, GLenum type)
1492 {
1493    struct st_context *st = st_context(ctx);
1494    struct pipe_context *pipe = st->pipe;
1495    struct pipe_screen *screen = st->screen;
1496    struct gl_pixelstore_attrib pack, unpack;
1497    GLint readX, readY, readW, readH, drawX, drawY, drawW, drawH;
1498 
1499    if (type == GL_DEPTH_STENCIL_TO_RGBA_NV || type == GL_DEPTH_STENCIL_TO_BGRA_NV)
1500       return GL_FALSE;
1501 
1502    if (ctx->Pixel.ZoomX == 1.0 &&
1503        ctx->Pixel.ZoomY == 1.0 &&
1504        (type != GL_COLOR ||
1505         (ctx->_ImageTransferState == 0x0 &&
1506          !ctx->Color.BlendEnabled &&
1507          !ctx->Color.AlphaEnabled &&
1508          (!ctx->Color.ColorLogicOpEnabled || ctx->Color.LogicOp == GL_COPY) &&
1509          !ctx->Depth.BoundsTest &&
1510          (!ctx->Depth.Test || (ctx->Depth.Func == GL_ALWAYS && !ctx->Depth.Mask)) &&
1511          !ctx->Fog.Enabled &&
1512          (!ctx->Stencil.Enabled ||
1513           (ctx->Stencil.FailFunc[0] == GL_KEEP &&
1514            ctx->Stencil.ZPassFunc[0] == GL_KEEP &&
1515            ctx->Stencil.ZFailFunc[0] == GL_KEEP)) &&
1516          !ctx->FragmentProgram.Enabled &&
1517          !ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT] &&
1518          !_mesa_ati_fragment_shader_enabled(ctx) &&
1519          ctx->DrawBuffer->_NumColorDrawBuffers == 1)) &&
1520        !ctx->Query.CurrentOcclusionObject) {
1521       struct gl_renderbuffer *rbRead, *rbDraw;
1522 
1523       /*
1524        * Clip the read region against the src buffer bounds.
1525        * We'll still allocate a temporary buffer/texture for the original
1526        * src region size but we'll only read the region which is on-screen.
1527        * This may mean that we draw garbage pixels into the dest region, but
1528        * that's expected.
1529        */
1530       readX = srcx;
1531       readY = srcy;
1532       readW = width;
1533       readH = height;
1534       pack = ctx->DefaultPacking;
1535       if (!_mesa_clip_readpixels(ctx, &readX, &readY, &readW, &readH, &pack))
1536          return GL_TRUE; /* all done */
1537 
1538       /* clip against dest buffer bounds and scissor box */
1539       drawX = dstx + pack.SkipPixels;
1540       drawY = dsty + pack.SkipRows;
1541       unpack = pack;
1542       if (!_mesa_clip_drawpixels(ctx, &drawX, &drawY, &readW, &readH, &unpack))
1543          return GL_TRUE; /* all done */
1544 
1545       readX = readX - pack.SkipPixels + unpack.SkipPixels;
1546       readY = readY - pack.SkipRows + unpack.SkipRows;
1547 
1548       drawW = readW;
1549       drawH = readH;
1550 
1551       if (type == GL_COLOR) {
1552          rbRead = st_get_color_read_renderbuffer(ctx);
1553          rbDraw = ctx->DrawBuffer->_ColorDrawBuffers[0];
1554       } else if (type == GL_DEPTH || type == GL_DEPTH_STENCIL) {
1555          rbRead = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
1556          rbDraw = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
1557       } else if (type == GL_STENCIL) {
1558          rbRead = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
1559          rbDraw = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
1560       } else {
1561          return false;
1562       }
1563 
1564       /* Flip src/dst position depending on the orientation of buffers. */
1565       if (_mesa_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
1566          readY = rbRead->Height - readY;
1567          readH = -readH;
1568       }
1569 
1570       if (_mesa_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
1571          /* We can't flip the destination for pipe->blit, so we only adjust
1572           * its position and flip the source.
1573           */
1574          drawY = rbDraw->Height - drawY - drawH;
1575          readY += readH;
1576          readH = -readH;
1577       }
1578 
1579       if (rbRead != rbDraw ||
1580           !_mesa_regions_overlap(readX, readY, readX + readW, readY + readH,
1581                                  drawX, drawY, drawX + drawW, drawY + drawH)) {
1582          struct pipe_blit_info blit;
1583 
1584          memset(&blit, 0, sizeof(blit));
1585          blit.src.resource = rbRead->texture;
1586          blit.src.level = rbRead->surface->u.tex.level;
1587          blit.src.format = rbRead->texture->format;
1588          blit.src.box.x = readX;
1589          blit.src.box.y = readY;
1590          blit.src.box.z = rbRead->surface->u.tex.first_layer;
1591          blit.src.box.width = readW;
1592          blit.src.box.height = readH;
1593          blit.src.box.depth = 1;
1594          blit.dst.resource = rbDraw->texture;
1595          blit.dst.level = rbDraw->surface->u.tex.level;
1596          blit.dst.format = rbDraw->texture->format;
1597          blit.dst.box.x = drawX;
1598          blit.dst.box.y = drawY;
1599          blit.dst.box.z = rbDraw->surface->u.tex.first_layer;
1600          blit.dst.box.width = drawW;
1601          blit.dst.box.height = drawH;
1602          blit.dst.box.depth = 1;
1603          blit.filter = PIPE_TEX_FILTER_NEAREST;
1604          blit.render_condition_enable = ctx->Query.CondRenderQuery != NULL;
1605 
1606          if (type == GL_COLOR)
1607             blit.mask |= PIPE_MASK_RGBA;
1608          if (type == GL_DEPTH)
1609             blit.mask |= PIPE_MASK_Z;
1610          if (type == GL_STENCIL)
1611             blit.mask |= PIPE_MASK_S;
1612          if (type == GL_DEPTH_STENCIL)
1613             blit.mask |= PIPE_MASK_ZS;
1614 
1615          if (ctx->DrawBuffer != ctx->WinSysDrawBuffer)
1616             st_window_rectangles_to_blit(ctx, &blit);
1617 
1618          if (screen->is_format_supported(screen, blit.src.format,
1619                                          blit.src.resource->target,
1620                                          blit.src.resource->nr_samples,
1621                                          blit.src.resource->nr_storage_samples,
1622                                          PIPE_BIND_SAMPLER_VIEW) &&
1623              screen->is_format_supported(screen, blit.dst.format,
1624                                          blit.dst.resource->target,
1625                                          blit.dst.resource->nr_samples,
1626                                          blit.dst.resource->nr_storage_samples,
1627                                          PIPE_BIND_RENDER_TARGET)) {
1628             pipe->blit(pipe, &blit);
1629             return GL_TRUE;
1630          }
1631       }
1632    }
1633 
1634    return GL_FALSE;
1635 }
1636 
1637 void
st_CopyPixels(struct gl_context * ctx,GLint srcx,GLint srcy,GLsizei width,GLsizei height,GLint dstx,GLint dsty,GLenum type)1638 st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
1639               GLsizei width, GLsizei height,
1640               GLint dstx, GLint dsty, GLenum type)
1641 {
1642    struct st_context *st = st_context(ctx);
1643    struct pipe_context *pipe = st->pipe;
1644    struct pipe_screen *screen = st->screen;
1645    struct gl_renderbuffer *rbRead;
1646    void *driver_fp;
1647    struct pipe_resource *pt;
1648    struct pipe_sampler_view *sv[2] = { NULL };
1649    struct st_fp_variant *fpv = NULL;
1650    int num_sampler_view = 1;
1651    enum pipe_format srcFormat;
1652    unsigned srcBind;
1653    GLboolean invertTex = GL_FALSE;
1654    GLint readX, readY, readW, readH;
1655    struct gl_pixelstore_attrib pack = ctx->DefaultPacking;
1656    GLboolean write_stencil = GL_FALSE;
1657    GLboolean write_depth = GL_FALSE;
1658 
1659    _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer);
1660 
1661    st_flush_bitmap_cache(st);
1662    st_invalidate_readpix_cache(st);
1663 
1664    st_validate_state(st, ST_PIPELINE_META_STATE_MASK);
1665 
1666    if (blit_copy_pixels(ctx, srcx, srcy, width, height, dstx, dsty, type))
1667       return;
1668 
1669    /* fallback if the driver can't do stencil exports */
1670    if (type == GL_DEPTH_STENCIL &&
1671        !st->has_stencil_export) {
1672       st_CopyPixels(ctx, srcx, srcy, width, height, dstx, dsty, GL_STENCIL);
1673       st_CopyPixels(ctx, srcx, srcy, width, height, dstx, dsty, GL_DEPTH);
1674       return;
1675    }
1676 
1677    /* fallback if the driver can't do stencil exports */
1678    if (type == GL_STENCIL &&
1679        !st->has_stencil_export) {
1680       copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty);
1681       return;
1682    }
1683 
1684    /*
1685     * The subsequent code implements glCopyPixels by copying the source
1686     * pixels into a temporary texture that's then applied to a textured quad.
1687     * When we draw the textured quad, all the usual per-fragment operations
1688     * are handled.
1689     */
1690 
1691    st_make_passthrough_vertex_shader(st);
1692 
1693    /*
1694     * Get vertex/fragment shaders
1695     */
1696    if (type == GL_COLOR) {
1697       fpv = get_color_fp_variant(st);
1698 
1699       rbRead = st_get_color_read_renderbuffer(ctx);
1700 
1701       driver_fp = fpv->base.driver_shader;
1702 
1703       if (ctx->Pixel.MapColorFlag) {
1704          pipe_sampler_view_reference(&sv[1],
1705                                      st->pixel_xfer.pixelmap_sampler_view);
1706          num_sampler_view++;
1707       }
1708 
1709       /* compiling a new fragment shader variant added new state constants
1710        * into the constant buffer, we need to update them
1711        */
1712       st_upload_constants(st, ctx->FragmentProgram._Current, MESA_SHADER_FRAGMENT);
1713    } else if (type == GL_DEPTH) {
1714       rbRead = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
1715       driver_fp = get_drawpix_z_stencil_program(st, GL_TRUE, GL_FALSE);
1716    } else if (type == GL_STENCIL) {
1717       rbRead = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
1718       driver_fp = get_drawpix_z_stencil_program(st, GL_FALSE, GL_TRUE);
1719    } else if (type == GL_DEPTH_STENCIL) {
1720       rbRead = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
1721       driver_fp = get_drawpix_z_stencil_program(st, GL_TRUE, GL_TRUE);
1722    } else {
1723       assert(type == GL_DEPTH_STENCIL_TO_RGBA_NV || type == GL_DEPTH_STENCIL_TO_BGRA_NV);
1724       rbRead = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
1725       if (type == GL_DEPTH_STENCIL_TO_RGBA_NV)
1726          driver_fp = get_drawpix_zs_to_color_program(st, GL_TRUE);
1727       else
1728          driver_fp = get_drawpix_zs_to_color_program(st, GL_FALSE);
1729       if (!driver_fp) {
1730          assert(0 && "operation not supported by CopyPixels implemetation");
1731          return;
1732       }
1733    }
1734 
1735 
1736    /* Choose the format for the temporary texture. */
1737    srcFormat = rbRead->texture->format;
1738    srcBind = PIPE_BIND_SAMPLER_VIEW |
1739       (type == GL_COLOR ? PIPE_BIND_RENDER_TARGET : PIPE_BIND_DEPTH_STENCIL);
1740 
1741    if (!screen->is_format_supported(screen, srcFormat, st->internal_target, 0,
1742                                     0, srcBind)) {
1743       /* srcFormat is non-renderable. Find a compatible renderable format. */
1744       if (type == GL_DEPTH) {
1745          srcFormat = st_choose_format(st, GL_DEPTH_COMPONENT, GL_NONE,
1746                                       GL_NONE, st->internal_target, 0, 0,
1747                                       srcBind, false, false);
1748       }
1749       else if (type == GL_STENCIL) {
1750          /* can't use texturing, fallback to copy */
1751          copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty);
1752          return;
1753       }
1754       else {
1755          assert(type == GL_COLOR);
1756 
1757          if (util_format_is_float(srcFormat)) {
1758             srcFormat = st_choose_format(st, GL_RGBA32F, GL_NONE,
1759                                          GL_NONE, st->internal_target, 0, 0,
1760                                          srcBind, false, false);
1761          }
1762          else if (util_format_is_pure_sint(srcFormat)) {
1763             srcFormat = st_choose_format(st, GL_RGBA32I, GL_NONE,
1764                                          GL_NONE, st->internal_target, 0, 0,
1765                                          srcBind, false, false);
1766          }
1767          else if (util_format_is_pure_uint(srcFormat)) {
1768             srcFormat = st_choose_format(st, GL_RGBA32UI, GL_NONE,
1769                                          GL_NONE, st->internal_target, 0, 0,
1770                                          srcBind, false, false);
1771          }
1772          else if (util_format_is_snorm(srcFormat)) {
1773             srcFormat = st_choose_format(st, GL_RGBA16_SNORM, GL_NONE,
1774                                          GL_NONE, st->internal_target, 0, 0,
1775                                          srcBind, false, false);
1776          }
1777          else {
1778             srcFormat = st_choose_format(st, GL_RGBA, GL_NONE,
1779                                          GL_NONE, st->internal_target, 0, 0,
1780                                          srcBind, false, false);
1781          }
1782       }
1783 
1784       if (srcFormat == PIPE_FORMAT_NONE) {
1785          assert(0 && "cannot choose a format for src of CopyPixels");
1786          return;
1787       }
1788    }
1789 
1790    /* Invert src region if needed */
1791    if (_mesa_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
1792       srcy = ctx->ReadBuffer->Height - srcy - height;
1793       invertTex = !invertTex;
1794    }
1795 
1796    /* Clip the read region against the src buffer bounds.
1797     * We'll still allocate a temporary buffer/texture for the original
1798     * src region size but we'll only read the region which is on-screen.
1799     * This may mean that we draw garbage pixels into the dest region, but
1800     * that's expected.
1801     */
1802    readX = srcx;
1803    readY = srcy;
1804    readW = width;
1805    readH = height;
1806    if (!_mesa_clip_readpixels(ctx, &readX, &readY, &readW, &readH, &pack)) {
1807       /* The source region is completely out of bounds.  Do nothing.
1808        * The GL spec says "Results of copies from outside the window,
1809        * or from regions of the window that are not exposed, are
1810        * hardware dependent and undefined."
1811        */
1812       return;
1813    }
1814 
1815    readW = MAX2(0, readW);
1816    readH = MAX2(0, readH);
1817 
1818    /* Allocate the temporary texture. */
1819    pt = alloc_texture(st, width, height, srcFormat, srcBind);
1820    if (!pt)
1821       return;
1822 
1823    sv[0] = st_create_texture_sampler_view(st->pipe, pt);
1824    if (!sv[0]) {
1825       pipe_resource_reference(&pt, NULL);
1826       return;
1827    }
1828 
1829    /* Create a second sampler view to read stencil */
1830    if (type == GL_STENCIL || type == GL_DEPTH_STENCIL ||
1831        type == GL_DEPTH_STENCIL_TO_RGBA_NV || type == GL_DEPTH_STENCIL_TO_BGRA_NV) {
1832       write_stencil = GL_TRUE;
1833       if (type == GL_DEPTH_STENCIL)
1834          write_depth = GL_TRUE;
1835       if (type == GL_DEPTH_STENCIL_TO_RGBA_NV || type == GL_DEPTH_STENCIL_TO_BGRA_NV) {
1836          write_depth = false;
1837          write_stencil = false;
1838       }
1839 
1840       enum pipe_format stencil_format =
1841          util_format_stencil_only(pt->format);
1842       /* we should not be doing pixel map/transfer (see above) */
1843       assert(num_sampler_view == 1);
1844       sv[1] = st_create_texture_sampler_view_format(st->pipe, pt,
1845                                                     stencil_format);
1846       if (!sv[1]) {
1847          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
1848          pipe_resource_reference(&pt, NULL);
1849          pipe_sampler_view_reference(&sv[0], NULL);
1850          return;
1851       }
1852       num_sampler_view++;
1853    }
1854    /* Copy the src region to the temporary texture. */
1855    {
1856       struct pipe_blit_info blit;
1857 
1858       memset(&blit, 0, sizeof(blit));
1859       blit.src.resource = rbRead->texture;
1860       blit.src.level = rbRead->surface->u.tex.level;
1861       blit.src.format = rbRead->texture->format;
1862       blit.src.box.x = readX;
1863       blit.src.box.y = readY;
1864       blit.src.box.z = rbRead->surface->u.tex.first_layer;
1865       blit.src.box.width = readW;
1866       blit.src.box.height = readH;
1867       blit.src.box.depth = 1;
1868       blit.dst.resource = pt;
1869       blit.dst.level = 0;
1870       blit.dst.format = pt->format;
1871       blit.dst.box.x = pack.SkipPixels;
1872       blit.dst.box.y = pack.SkipRows;
1873       blit.dst.box.z = 0;
1874       blit.dst.box.width = readW;
1875       blit.dst.box.height = readH;
1876       blit.dst.box.depth = 1;
1877       if (type == GL_DEPTH)
1878           blit.mask = util_format_get_mask(pt->format) & ~PIPE_MASK_S;
1879       else if (type == GL_STENCIL)
1880           blit.mask = util_format_get_mask(pt->format) & ~PIPE_MASK_Z;
1881       else
1882          blit.mask = util_format_get_mask(pt->format);
1883       blit.filter = PIPE_TEX_FILTER_NEAREST;
1884 
1885       pipe->blit(pipe, &blit);
1886    }
1887 
1888    /* OK, the texture 'pt' contains the src image/pixels.  Now draw a
1889     * textured quad with that texture.
1890     */
1891 
1892    draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2],
1893                       width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
1894                       sv,
1895                       num_sampler_view,
1896                       st->passthrough_vs,
1897                       driver_fp, fpv,
1898                       ctx->Current.Attrib[VERT_ATTRIB_COLOR0],
1899                       invertTex, write_depth, write_stencil);
1900 
1901    pipe_resource_reference(&pt, NULL);
1902 }
1903 
1904 void
st_destroy_drawpix(struct st_context * st)1905 st_destroy_drawpix(struct st_context *st)
1906 {
1907    GLuint i;
1908 
1909    for (i = 0; i < ARRAY_SIZE(st->drawpix.zs_shaders); i++) {
1910       if (st->drawpix.zs_shaders[i])
1911          st->pipe->delete_fs_state(st->pipe, st->drawpix.zs_shaders[i]);
1912    }
1913 
1914    if (st->passthrough_vs)
1915       st->pipe->delete_vs_state(st->pipe, st->passthrough_vs);
1916 
1917    /* Free cache data */
1918    for (i = 0; i < ARRAY_SIZE(st->drawpix_cache.entries); i++) {
1919       struct drawpix_cache_entry *entry = &st->drawpix_cache.entries[i];
1920       free(entry->image);
1921       pipe_resource_reference(&entry->texture, NULL);
1922    }
1923 }
1924