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 if (memcmp(&entry->pixelmaps, &st->ctx->PixelMaps,
489 sizeof(struct gl_pixelmaps)) != 0)
490 continue;
491
492 /* check if the pixel data is the same */
493 if (memcmp(pixels, entry->image, width * height * bpp) == 0) {
494 /* Success - found a cache match */
495 pipe_resource_reference(&pt, entry->texture);
496 /* refcount of returned texture should be at least two here. One
497 * reference for the cache to hold on to, one for the caller (which
498 * it will release), and possibly more held by the driver.
499 */
500 assert(pt->reference.count >= 2);
501
502 /* update the age of this entry */
503 entry->age = ++st->drawpix_cache.age;
504
505 return pt;
506 }
507 }
508 }
509
510 /* no cache match found */
511 return NULL;
512 }
513
514
515 /**
516 * Find the oldest entry in the glDrawPixels cache. We'll replace this
517 * one when we need to store a new image.
518 */
519 static struct drawpix_cache_entry *
find_oldest_drawpixels_cache_entry(struct st_context * st)520 find_oldest_drawpixels_cache_entry(struct st_context *st)
521 {
522 unsigned oldest_age = ~0u, oldest_index = ~0u;
523 unsigned i;
524
525 /* Find entry with oldest (lowest) age */
526 for (i = 0; i < ARRAY_SIZE(st->drawpix_cache.entries); i++) {
527 const struct drawpix_cache_entry *entry = &st->drawpix_cache.entries[i];
528 if (entry->age < oldest_age) {
529 oldest_age = entry->age;
530 oldest_index = i;
531 }
532 }
533
534 assert(oldest_index != ~0u);
535
536 return &st->drawpix_cache.entries[oldest_index];
537 }
538
539
540 /**
541 * Try to save the given glDrawPixels image in the cache.
542 */
543 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)544 cache_drawpixels_image(struct st_context *st,
545 GLsizei width, GLsizei height,
546 GLenum format, GLenum type,
547 const struct gl_pixelstore_attrib *unpack,
548 const void *pixels,
549 struct pipe_resource *pt)
550 {
551 if ((unpack->RowLength == 0 || unpack->RowLength == width) &&
552 unpack->SkipPixels == 0 &&
553 unpack->SkipRows == 0) {
554 const GLint bpp = _mesa_bytes_per_pixel(format, type);
555 struct drawpix_cache_entry *entry =
556 find_oldest_drawpixels_cache_entry(st);
557 assert(entry);
558 entry->width = width;
559 entry->height = height;
560 entry->format = format;
561 entry->type = type;
562 memcpy(&entry->pixelmaps, &st->ctx->PixelMaps,
563 sizeof(struct gl_pixelmaps));
564 entry->user_pointer = pixels;
565 free(entry->image);
566 entry->image = malloc(width * height * bpp);
567 if (entry->image) {
568 memcpy(entry->image, pixels, width * height * bpp);
569 pipe_resource_reference(&entry->texture, pt);
570 entry->age = ++st->drawpix_cache.age;
571 }
572 else {
573 /* out of memory, free/disable cached texture */
574 entry->width = 0;
575 entry->height = 0;
576 pipe_resource_reference(&entry->texture, NULL);
577 }
578 }
579 }
580
581
582 /**
583 * Make texture containing an image for glDrawPixels image.
584 * If 'pixels' is NULL, leave the texture image data undefined.
585 */
586 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)587 make_texture(struct st_context *st,
588 GLsizei width, GLsizei height, GLenum format, GLenum type,
589 const struct gl_pixelstore_attrib *unpack,
590 const void *pixels)
591 {
592 struct gl_context *ctx = st->ctx;
593 struct pipe_context *pipe = st->pipe;
594 mesa_format mformat;
595 struct pipe_resource *pt = NULL;
596 enum pipe_format pipeFormat;
597 GLenum baseInternalFormat;
598
599 #if USE_DRAWPIXELS_CACHE
600 pt = search_drawpixels_cache(st, width, height, format, type,
601 unpack, pixels);
602 if (pt) {
603 return pt;
604 }
605 #endif
606
607 /* Choose a pixel format for the temp texture which will hold the
608 * image to draw.
609 */
610 pipeFormat = st_choose_matching_format(st, PIPE_BIND_SAMPLER_VIEW,
611 format, type, unpack->SwapBytes);
612
613 if (pipeFormat == PIPE_FORMAT_NONE) {
614 /* Use the generic approach. */
615 GLenum intFormat = internal_format(ctx, format, type);
616
617 pipeFormat = st_choose_format(st, intFormat, format, type,
618 st->internal_target, 0, 0,
619 PIPE_BIND_SAMPLER_VIEW,
620 false, false);
621 assert(pipeFormat != PIPE_FORMAT_NONE);
622 }
623
624 mformat = st_pipe_format_to_mesa_format(pipeFormat);
625 baseInternalFormat = _mesa_get_format_base_format(mformat);
626
627 pixels = _mesa_map_pbo_source(ctx, unpack, pixels);
628 if (!pixels)
629 return NULL;
630
631 /* alloc temporary texture */
632 pt = alloc_texture(st, width, height, pipeFormat, PIPE_BIND_SAMPLER_VIEW);
633 if (!pt) {
634 _mesa_unmap_pbo_source(ctx, unpack);
635 return NULL;
636 }
637
638 {
639 struct pipe_transfer *transfer;
640 GLubyte *dest;
641 const GLbitfield imageTransferStateSave = ctx->_ImageTransferState;
642
643 /* we'll do pixel transfer in a fragment shader */
644 ctx->_ImageTransferState = 0x0;
645
646 /* map texture transfer */
647 dest = pipe_texture_map(pipe, pt, 0, 0,
648 PIPE_MAP_WRITE | PIPE_MAP_DISCARD_WHOLE_RESOURCE,
649 0, 0, width, height, &transfer);
650 if (!dest) {
651 pipe_resource_reference(&pt, NULL);
652 _mesa_unmap_pbo_source(ctx, unpack);
653 return NULL;
654 }
655
656 /* Put image into texture transfer.
657 * Note that the image is actually going to be upside down in
658 * the texture. We deal with that with texcoords.
659 */
660 if ((format == GL_RGBA || format == GL_BGRA)
661 && type == GL_UNSIGNED_BYTE) {
662 /* Use a memcpy-based texstore to avoid software pixel swizzling.
663 * We'll do the necessary swizzling with the pipe_sampler_view to
664 * give much better performance.
665 * XXX in the future, expand this to accomodate more format and
666 * type combinations.
667 */
668 _mesa_memcpy_texture(ctx, 2,
669 mformat, /* mesa_format */
670 transfer->stride, /* dstRowStride, bytes */
671 &dest, /* destSlices */
672 width, height, 1, /* size */
673 format, type, /* src format/type */
674 pixels, /* data source */
675 unpack);
676 }
677 else {
678 ASSERTED bool success;
679 success = _mesa_texstore(ctx, 2, /* dims */
680 baseInternalFormat, /* baseInternalFormat */
681 mformat, /* mesa_format */
682 transfer->stride, /* dstRowStride, bytes */
683 &dest, /* destSlices */
684 width, height, 1, /* size */
685 format, type, /* src format/type */
686 pixels, /* data source */
687 unpack);
688
689 assert(success);
690 }
691
692 /* unmap */
693 pipe_texture_unmap(pipe, transfer);
694
695 /* restore */
696 ctx->_ImageTransferState = imageTransferStateSave;
697 }
698
699 #if USE_DRAWPIXELS_CACHE
700 cache_drawpixels_image(st, width, height, format, type, unpack, pixels, pt);
701 #endif
702
703 _mesa_unmap_pbo_source(ctx, unpack);
704
705 return pt;
706 }
707
708
709 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)710 draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
711 GLsizei width, GLsizei height,
712 GLfloat zoomX, GLfloat zoomY,
713 struct pipe_sampler_view **sv,
714 int num_sampler_view,
715 void *driver_vp,
716 void *driver_fp,
717 struct st_fp_variant *fpv,
718 const GLfloat *color,
719 GLboolean invertTex,
720 GLboolean write_depth, GLboolean write_stencil)
721 {
722 struct st_context *st = st_context(ctx);
723 struct pipe_context *pipe = st->pipe;
724 struct cso_context *cso = st->cso_context;
725 const unsigned fb_width = _mesa_geometric_width(ctx->DrawBuffer);
726 const unsigned fb_height = _mesa_geometric_height(ctx->DrawBuffer);
727 GLfloat x0, y0, x1, y1;
728 ASSERTED GLsizei maxSize;
729 bool normalized = sv[0]->texture->target == PIPE_TEXTURE_2D ||
730 (sv[0]->texture->target == PIPE_TEXTURE_RECT && st->lower_rect_tex);
731 unsigned cso_state_mask;
732
733 assert(sv[0]->texture->target == st->internal_target);
734
735 /* limit checks */
736 /* XXX if DrawPixels image is larger than max texture size, break
737 * it up into chunks.
738 */
739 maxSize = st->screen->caps.max_texture_2d_size;
740 assert(width <= maxSize);
741 assert(height <= maxSize);
742
743 cso_state_mask = (CSO_BIT_RASTERIZER |
744 CSO_BIT_VIEWPORT |
745 CSO_BIT_FRAGMENT_SAMPLERS |
746 CSO_BIT_STREAM_OUTPUTS |
747 CSO_BIT_VERTEX_ELEMENTS |
748 CSO_BITS_ALL_SHADERS);
749 if (write_stencil) {
750 cso_state_mask |= (CSO_BIT_DEPTH_STENCIL_ALPHA |
751 CSO_BIT_BLEND);
752 }
753 cso_save_state(cso, cso_state_mask);
754
755 /* rasterizer state: just scissor */
756 {
757 struct pipe_rasterizer_state rasterizer;
758 memset(&rasterizer, 0, sizeof(rasterizer));
759 rasterizer.clamp_fragment_color = !st->clamp_frag_color_in_shader &&
760 ctx->Color._ClampFragmentColor;
761 rasterizer.half_pixel_center = 1;
762 rasterizer.bottom_edge_rule = 1;
763 rasterizer.depth_clip_near = !ctx->Transform.DepthClampNear;
764 rasterizer.depth_clip_far = !ctx->Transform.DepthClampFar;
765 rasterizer.depth_clamp = !rasterizer.depth_clip_far;
766 rasterizer.scissor = ctx->Scissor.EnableFlags;
767 cso_set_rasterizer(cso, &rasterizer);
768 }
769
770 if (write_stencil) {
771 /* Stencil writing bypasses the normal fragment pipeline to
772 * disable color writing and set stencil test to always pass.
773 */
774 struct pipe_depth_stencil_alpha_state dsa;
775 struct pipe_blend_state blend;
776
777 /* depth/stencil */
778 memset(&dsa, 0, sizeof(dsa));
779 dsa.stencil[0].enabled = 1;
780 dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
781 dsa.stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff;
782 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
783 if (write_depth) {
784 /* writing depth+stencil: depth test always passes */
785 dsa.depth_enabled = 1;
786 dsa.depth_writemask = ctx->Depth.Mask;
787 dsa.depth_func = PIPE_FUNC_ALWAYS;
788 }
789 cso_set_depth_stencil_alpha(cso, &dsa);
790
791 /* blend (colormask) */
792 memset(&blend, 0, sizeof(blend));
793 cso_set_blend(cso, &blend);
794 }
795
796 /* fragment shader state: TEX lookup program */
797 cso_set_fragment_shader_handle(cso, driver_fp);
798
799 /* vertex shader state: position + texcoord pass-through */
800 cso_set_vertex_shader_handle(cso, driver_vp);
801
802 /* disable other shaders */
803 cso_set_tessctrl_shader_handle(cso, NULL);
804 cso_set_tesseval_shader_handle(cso, NULL);
805 cso_set_geometry_shader_handle(cso, NULL);
806
807 /* user samplers, plus the drawpix samplers */
808 {
809 struct pipe_sampler_state sampler;
810
811 memset(&sampler, 0, sizeof(sampler));
812 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
813 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
814 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
815 sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
816 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
817 sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
818 sampler.unnormalized_coords = !normalized;
819
820 if (fpv) {
821 /* drawing a color image */
822 const struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
823 uint num = MAX3(fpv->drawpix_sampler + 1,
824 fpv->pixelmap_sampler + 1,
825 st->state.num_frag_samplers);
826 uint i;
827
828 for (i = 0; i < st->state.num_frag_samplers; i++)
829 samplers[i] = &st->state.frag_samplers[i];
830
831 samplers[fpv->drawpix_sampler] = &sampler;
832 if (sv[1])
833 samplers[fpv->pixelmap_sampler] = &sampler;
834
835 cso_set_samplers(cso, PIPE_SHADER_FRAGMENT, num, samplers);
836 } else {
837 /* drawing a depth/stencil image */
838 const struct pipe_sampler_state *samplers[2] = {&sampler, &sampler};
839
840 cso_set_samplers(cso, PIPE_SHADER_FRAGMENT, num_sampler_view, samplers);
841 }
842 }
843
844 unsigned tex_width = sv[0]->texture->width0;
845 unsigned tex_height = sv[0]->texture->height0;
846
847 /* user textures, plus the drawpix textures */
848 if (fpv) {
849 /* drawing a color image */
850 struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
851 unsigned num_views =
852 st_get_sampler_views(st, PIPE_SHADER_FRAGMENT,
853 ctx->FragmentProgram._Current, sampler_views);
854
855 num_views = MAX3(fpv->drawpix_sampler + 1, fpv->pixelmap_sampler + 1,
856 num_views);
857
858 sampler_views[fpv->drawpix_sampler] = sv[0];
859 if (sv[1])
860 sampler_views[fpv->pixelmap_sampler] = sv[1];
861 pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, num_views, 0,
862 true, sampler_views);
863 st->state.num_sampler_views[PIPE_SHADER_FRAGMENT] = num_views;
864 } else {
865 /* drawing a depth/stencil image */
866 pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, num_sampler_view,
867 0, false, sv);
868 st->state.num_sampler_views[PIPE_SHADER_FRAGMENT] =
869 MAX2(st->state.num_sampler_views[PIPE_SHADER_FRAGMENT], num_sampler_view);
870
871 for (unsigned i = 0; i < num_sampler_view; i++)
872 pipe_sampler_view_reference(&sv[i], NULL);
873 }
874
875 /* viewport state: viewport matching window dims */
876 cso_set_viewport_dims(cso, fb_width, fb_height, true);
877
878 st->util_velems.count = 3;
879 cso_set_vertex_elements(cso, &st->util_velems);
880 cso_set_stream_outputs(cso, 0, NULL, NULL, 0);
881
882 /* Compute Gallium window coords (y=0=top) with pixel zoom.
883 * Recall that these coords are transformed by the current
884 * vertex shader and viewport transformation.
885 */
886 if (_mesa_fb_orientation(ctx->DrawBuffer) == Y_0_BOTTOM) {
887 y = fb_height - (int) (y + height * ctx->Pixel.ZoomY);
888 invertTex = !invertTex;
889 }
890
891 x0 = (GLfloat) x;
892 x1 = x + width * ctx->Pixel.ZoomX;
893 y0 = (GLfloat) y;
894 y1 = y + height * ctx->Pixel.ZoomY;
895
896 /* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */
897 z = z * 2.0f - 1.0f;
898
899 {
900 const float clip_x0 = x0 / (float) fb_width * 2.0f - 1.0f;
901 const float clip_y0 = y0 / (float) fb_height * 2.0f - 1.0f;
902 const float clip_x1 = x1 / (float) fb_width * 2.0f - 1.0f;
903 const float clip_y1 = y1 / (float) fb_height * 2.0f - 1.0f;
904 const float maxXcoord = normalized ?
905 ((float) width / tex_width) : (float) width;
906 const float maxYcoord = normalized
907 ? ((float) height / tex_height) : (float) height;
908 const float sLeft = 0.0f, sRight = maxXcoord;
909 const float tTop = invertTex ? maxYcoord : 0.0f;
910 const float tBot = invertTex ? 0.0f : maxYcoord;
911
912 if (!st_draw_quad(st, clip_x0, clip_y0, clip_x1, clip_y1, z,
913 sLeft, tBot, sRight, tTop, color, 0)) {
914 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
915 }
916 }
917
918 /* restore state */
919 /* Unbind all because st/mesa won't do it if the current shader doesn't
920 * use them.
921 */
922 cso_restore_state(cso, CSO_UNBIND_FS_SAMPLERVIEWS);
923 st->state.num_sampler_views[PIPE_SHADER_FRAGMENT] = 0;
924
925 ctx->Array.NewVertexElements = true;
926 ctx->NewDriverState |= ST_NEW_VERTEX_ARRAYS |
927 ST_NEW_FS_SAMPLER_VIEWS;
928 }
929
930
931 /**
932 * Software fallback to do glDrawPixels(GL_STENCIL_INDEX) when we
933 * can't use a fragment shader to write stencil values.
934 */
935 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)936 draw_stencil_pixels(struct gl_context *ctx, GLint x, GLint y,
937 GLsizei width, GLsizei height, GLenum format, GLenum type,
938 const struct gl_pixelstore_attrib *unpack,
939 const void *pixels)
940 {
941 struct st_context *st = st_context(ctx);
942 struct pipe_context *pipe = st->pipe;
943 struct gl_renderbuffer *rb;
944 enum pipe_map_flags usage;
945 struct pipe_transfer *pt;
946 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
947 uint8_t *stmap;
948 struct gl_pixelstore_attrib clippedUnpack = *unpack;
949 GLubyte *sValues;
950 GLuint *zValues;
951
952 rb = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
953
954 if (_mesa_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
955 y = ctx->DrawBuffer->Height - y - height;
956 }
957
958 if (format == GL_STENCIL_INDEX &&
959 _mesa_is_format_packed_depth_stencil(rb->Format)) {
960 /* writing stencil to a combined depth+stencil buffer */
961 usage = PIPE_MAP_READ_WRITE;
962 }
963 else {
964 usage = PIPE_MAP_WRITE;
965 }
966
967 stmap = pipe_texture_map(pipe, rb->texture,
968 rb->surface->u.tex.level,
969 rb->surface->u.tex.first_layer,
970 usage, x, y,
971 width, height, &pt);
972
973 pixels = _mesa_map_pbo_source(ctx, &clippedUnpack, pixels);
974 assert(pixels);
975
976 sValues = malloc(width * sizeof(GLubyte));
977 zValues = malloc(width * sizeof(GLuint));
978
979 if (sValues && zValues) {
980 GLint row;
981 for (row = 0; row < height; row++) {
982 GLfloat *zValuesFloat = (GLfloat*)zValues;
983 GLenum destType = GL_UNSIGNED_BYTE;
984 const void *source = _mesa_image_address2d(&clippedUnpack, pixels,
985 width, height,
986 format, type,
987 row, 0);
988 _mesa_unpack_stencil_span(ctx, width, destType, sValues,
989 type, source, &clippedUnpack,
990 ctx->_ImageTransferState);
991
992 if (format == GL_DEPTH_STENCIL) {
993 GLenum ztype =
994 pt->resource->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT ?
995 GL_FLOAT : GL_UNSIGNED_INT;
996
997 _mesa_unpack_depth_span(ctx, width, ztype, zValues,
998 (1 << 24) - 1, type, source,
999 &clippedUnpack);
1000 }
1001
1002 if (zoom) {
1003 _mesa_problem(ctx, "Gallium glDrawPixels(GL_STENCIL) with "
1004 "zoom not complete");
1005 }
1006
1007 {
1008 GLint spanY;
1009
1010 if (_mesa_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
1011 spanY = height - row - 1;
1012 }
1013 else {
1014 spanY = row;
1015 }
1016
1017 /* now pack the stencil (and Z) values in the dest format */
1018 switch (pt->resource->format) {
1019 case PIPE_FORMAT_S8_UINT:
1020 {
1021 uint8_t *dest = stmap + spanY * pt->stride;
1022 assert(usage == PIPE_MAP_WRITE);
1023 memcpy(dest, sValues, width);
1024 }
1025 break;
1026 case PIPE_FORMAT_Z24_UNORM_S8_UINT:
1027 if (format == GL_DEPTH_STENCIL) {
1028 uint *dest = (uint *) (stmap + spanY * pt->stride);
1029 GLint k;
1030 assert(usage == PIPE_MAP_WRITE);
1031 for (k = 0; k < width; k++) {
1032 dest[k] = zValues[k] | (sValues[k] << 24);
1033 }
1034 }
1035 else {
1036 uint *dest = (uint *) (stmap + spanY * pt->stride);
1037 GLint k;
1038 assert(usage == PIPE_MAP_READ_WRITE);
1039 for (k = 0; k < width; k++) {
1040 dest[k] = (dest[k] & 0xffffff) | (sValues[k] << 24);
1041 }
1042 }
1043 break;
1044 case PIPE_FORMAT_S8_UINT_Z24_UNORM:
1045 if (format == GL_DEPTH_STENCIL) {
1046 uint *dest = (uint *) (stmap + spanY * pt->stride);
1047 GLint k;
1048 assert(usage == PIPE_MAP_WRITE);
1049 for (k = 0; k < width; k++) {
1050 dest[k] = (zValues[k] << 8) | (sValues[k] & 0xff);
1051 }
1052 }
1053 else {
1054 uint *dest = (uint *) (stmap + spanY * pt->stride);
1055 GLint k;
1056 assert(usage == PIPE_MAP_READ_WRITE);
1057 for (k = 0; k < width; k++) {
1058 dest[k] = (dest[k] & 0xffffff00) | (sValues[k] & 0xff);
1059 }
1060 }
1061 break;
1062 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
1063 if (format == GL_DEPTH_STENCIL) {
1064 uint *dest = (uint *) (stmap + spanY * pt->stride);
1065 GLfloat *destf = (GLfloat*)dest;
1066 GLint k;
1067 assert(usage == PIPE_MAP_WRITE);
1068 for (k = 0; k < width; k++) {
1069 destf[k*2] = zValuesFloat[k];
1070 dest[k*2+1] = sValues[k] & 0xff;
1071 }
1072 }
1073 else {
1074 uint *dest = (uint *) (stmap + spanY * pt->stride);
1075 GLint k;
1076 assert(usage == PIPE_MAP_READ_WRITE);
1077 for (k = 0; k < width; k++) {
1078 dest[k*2+1] = sValues[k] & 0xff;
1079 }
1080 }
1081 break;
1082 default:
1083 assert(0);
1084 }
1085 }
1086 }
1087 }
1088 else {
1089 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels()");
1090 }
1091
1092 free(sValues);
1093 free(zValues);
1094
1095 _mesa_unmap_pbo_source(ctx, &clippedUnpack);
1096
1097 /* unmap the stencil buffer */
1098 pipe_texture_unmap(pipe, pt);
1099 }
1100
1101
1102 /**
1103 * Get fragment program variant for a glDrawPixels or glCopyPixels
1104 * command for RGBA data.
1105 */
1106 static struct st_fp_variant *
get_color_fp_variant(struct st_context * st)1107 get_color_fp_variant(struct st_context *st)
1108 {
1109 struct gl_context *ctx = st->ctx;
1110 struct st_fp_variant_key key;
1111 struct st_fp_variant *fpv;
1112
1113 memset(&key, 0, sizeof(key));
1114
1115 key.st = st->has_shareable_shaders ? NULL : st;
1116 key.drawpixels = 1;
1117 key.scaleAndBias = (ctx->Pixel.RedBias != 0.0 ||
1118 ctx->Pixel.RedScale != 1.0 ||
1119 ctx->Pixel.GreenBias != 0.0 ||
1120 ctx->Pixel.GreenScale != 1.0 ||
1121 ctx->Pixel.BlueBias != 0.0 ||
1122 ctx->Pixel.BlueScale != 1.0 ||
1123 ctx->Pixel.AlphaBias != 0.0 ||
1124 ctx->Pixel.AlphaScale != 1.0);
1125 key.pixelMaps = ctx->Pixel.MapColorFlag;
1126 key.clamp_color = st->clamp_frag_color_in_shader &&
1127 ctx->Color._ClampFragmentColor;
1128 key.lower_alpha_func = COMPARE_FUNC_ALWAYS;
1129
1130 fpv = st_get_fp_variant(st, ctx->FragmentProgram._Current, &key, false, NULL);
1131
1132 return fpv;
1133 }
1134
1135 /**
1136 * Get fragment program variant for a glDrawPixels command
1137 * for COLOR_INDEX data
1138 */
1139 static struct st_fp_variant *
get_color_index_fp_variant(struct st_context * st)1140 get_color_index_fp_variant(struct st_context *st)
1141 {
1142 struct gl_context *ctx = st->ctx;
1143 struct st_fp_variant_key key;
1144 struct st_fp_variant *fpv;
1145
1146 memset(&key, 0, sizeof(key));
1147
1148 key.st = st->has_shareable_shaders ? NULL : st;
1149 key.drawpixels = 1;
1150 /* Since GL is always in RGBA mode MapColorFlag does not
1151 * affect GL_COLOR_INDEX format.
1152 * Scale and bias also never affect GL_COLOR_INDEX format.
1153 */
1154 key.scaleAndBias = 0;
1155 key.pixelMaps = 0;
1156 key.clamp_color = st->clamp_frag_color_in_shader &&
1157 ctx->Color._ClampFragmentColor;
1158 key.lower_alpha_func = COMPARE_FUNC_ALWAYS;
1159
1160 fpv = st_get_fp_variant(st, ctx->FragmentProgram._Current, &key, false, NULL);
1161
1162 return fpv;
1163 }
1164
1165
1166 /**
1167 * Clamp glDrawPixels width and height to the maximum texture size.
1168 */
1169 static void
clamp_size(struct st_context * st,GLsizei * width,GLsizei * height,struct gl_pixelstore_attrib * unpack)1170 clamp_size(struct st_context *st, GLsizei *width, GLsizei *height,
1171 struct gl_pixelstore_attrib *unpack)
1172 {
1173 const int maxSize = st->screen->caps.max_texture_2d_size;
1174
1175 if (*width > maxSize) {
1176 if (unpack->RowLength == 0)
1177 unpack->RowLength = *width;
1178 *width = maxSize;
1179 }
1180 if (*height > maxSize) {
1181 *height = maxSize;
1182 }
1183 }
1184
1185
1186 /**
1187 * Search the array of 4 swizzle components for the named component and return
1188 * its position.
1189 */
1190 static unsigned
search_swizzle(const unsigned char swizzle[4],unsigned component)1191 search_swizzle(const unsigned char swizzle[4], unsigned component)
1192 {
1193 unsigned i;
1194 for (i = 0; i < 4; i++) {
1195 if (swizzle[i] == component)
1196 return i;
1197 }
1198 assert(!"search_swizzle() failed");
1199 return 0;
1200 }
1201
1202
1203 /**
1204 * Set the sampler view's swizzle terms. This is used to handle RGBA
1205 * swizzling when the incoming image format isn't an exact match for
1206 * the actual texture format. For example, if we have glDrawPixels(
1207 * GL_RGBA, GL_UNSIGNED_BYTE) and we chose the texture format
1208 * PIPE_FORMAT_B8G8R8A8 then we can do use the sampler view swizzle to
1209 * avoid swizzling all the pixels in software in the texstore code.
1210 */
1211 static void
setup_sampler_swizzle(struct pipe_sampler_view * sv,GLenum format,GLenum type)1212 setup_sampler_swizzle(struct pipe_sampler_view *sv, GLenum format, GLenum type)
1213 {
1214 if ((format == GL_RGBA || format == GL_BGRA) && type == GL_UNSIGNED_BYTE) {
1215 const struct util_format_description *desc =
1216 util_format_description(sv->format);
1217 unsigned c0, c1, c2, c3;
1218
1219 /* Every gallium driver supports at least one 32-bit packed RGBA format.
1220 * We must have chosen one for (GL_RGBA, GL_UNSIGNED_BYTE).
1221 */
1222 assert(desc->block.bits == 32);
1223
1224 /* invert the format's swizzle to setup the sampler's swizzle */
1225 if (format == GL_RGBA) {
1226 c0 = PIPE_SWIZZLE_X;
1227 c1 = PIPE_SWIZZLE_Y;
1228 c2 = PIPE_SWIZZLE_Z;
1229 c3 = PIPE_SWIZZLE_W;
1230 }
1231 else {
1232 assert(format == GL_BGRA);
1233 c0 = PIPE_SWIZZLE_Z;
1234 c1 = PIPE_SWIZZLE_Y;
1235 c2 = PIPE_SWIZZLE_X;
1236 c3 = PIPE_SWIZZLE_W;
1237 }
1238 sv->swizzle_r = search_swizzle(desc->swizzle, c0);
1239 sv->swizzle_g = search_swizzle(desc->swizzle, c1);
1240 sv->swizzle_b = search_swizzle(desc->swizzle, c2);
1241 sv->swizzle_a = search_swizzle(desc->swizzle, c3);
1242 }
1243 else {
1244 /* use the default sampler swizzle */
1245 }
1246 }
1247
1248 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)1249 st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
1250 GLsizei width, GLsizei height,
1251 GLenum format, GLenum type,
1252 const struct gl_pixelstore_attrib *unpack, const void *pixels)
1253 {
1254 void *driver_fp;
1255 struct st_context *st = st_context(ctx);
1256 GLboolean write_stencil = GL_FALSE, write_depth = GL_FALSE;
1257 struct pipe_sampler_view *sv[2] = { NULL };
1258 int num_sampler_view = 1;
1259 struct gl_pixelstore_attrib clippedUnpack;
1260 struct st_fp_variant *fpv = NULL;
1261 struct pipe_resource *pt;
1262
1263 /* Mesa state should be up to date by now */
1264 assert(ctx->NewState == 0x0);
1265
1266 _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer);
1267
1268 st_flush_bitmap_cache(st);
1269 st_invalidate_readpix_cache(st);
1270
1271 st_validate_state(st, ST_PIPELINE_META_STATE_MASK);
1272
1273 clippedUnpack = *unpack;
1274 unpack = &clippedUnpack;
1275
1276 /* Skip totally clipped DrawPixels. */
1277 if (ctx->Pixel.ZoomX == 1 && ctx->Pixel.ZoomY == 1 &&
1278 !_mesa_clip_drawpixels(ctx, &x, &y, &width, &height, &clippedUnpack))
1279 return;
1280
1281 /* Limit the size of the glDrawPixels to the max texture size.
1282 * Strictly speaking, that's not correct but since we don't handle
1283 * larger images yet, this is better than crashing.
1284 */
1285 clamp_size(st, &width, &height, &clippedUnpack);
1286
1287 if (format == GL_DEPTH_STENCIL)
1288 write_stencil = write_depth = GL_TRUE;
1289 else if (format == GL_STENCIL_INDEX)
1290 write_stencil = GL_TRUE;
1291 else if (format == GL_DEPTH_COMPONENT)
1292 write_depth = GL_TRUE;
1293
1294 if (write_stencil &&
1295 !st->has_stencil_export) {
1296 /* software fallback */
1297 draw_stencil_pixels(ctx, x, y, width, height, format, type,
1298 unpack, pixels);
1299 return;
1300 }
1301
1302 /* Put glDrawPixels image into a texture */
1303 pt = make_texture(st, width, height, format, type, unpack, pixels);
1304 if (!pt) {
1305 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
1306 return;
1307 }
1308
1309 st_make_passthrough_vertex_shader(st);
1310
1311 /*
1312 * Get vertex/fragment shaders
1313 */
1314 if (write_depth || write_stencil) {
1315 driver_fp = get_drawpix_z_stencil_program(st, write_depth,
1316 write_stencil);
1317 }
1318 else {
1319 fpv = (format != GL_COLOR_INDEX) ? get_color_fp_variant(st) :
1320 get_color_index_fp_variant(st);
1321
1322 driver_fp = fpv->base.driver_shader;
1323
1324 if (ctx->Pixel.MapColorFlag && format != GL_COLOR_INDEX) {
1325 pipe_sampler_view_reference(&sv[1],
1326 st->pixel_xfer.pixelmap_sampler_view);
1327 num_sampler_view++;
1328 }
1329
1330 /* compiling a new fragment shader variant added new state constants
1331 * into the constant buffer, we need to update them
1332 */
1333 st_upload_constants(st, ctx->FragmentProgram._Current, MESA_SHADER_FRAGMENT);
1334 }
1335
1336 {
1337 /* create sampler view for the image */
1338 struct pipe_sampler_view templ;
1339
1340 u_sampler_view_default_template(&templ, pt, pt->format);
1341 /* Set up the sampler view's swizzle */
1342 setup_sampler_swizzle(&templ, format, type);
1343
1344 sv[0] = st->pipe->create_sampler_view(st->pipe, pt, &templ);
1345 }
1346 if (!sv[0]) {
1347 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
1348 pipe_resource_reference(&pt, NULL);
1349 return;
1350 }
1351
1352 /* Create a second sampler view to read stencil. The stencil is
1353 * written using the shader stencil export functionality.
1354 */
1355 if (write_stencil) {
1356 enum pipe_format stencil_format =
1357 util_format_stencil_only(pt->format);
1358 /* we should not be doing pixel map/transfer (see above) */
1359 assert(num_sampler_view == 1);
1360 sv[1] = st_create_texture_sampler_view_format(st->pipe, pt,
1361 stencil_format);
1362 if (!sv[1]) {
1363 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
1364 pipe_resource_reference(&pt, NULL);
1365 pipe_sampler_view_reference(&sv[0], NULL);
1366 return;
1367 }
1368 num_sampler_view++;
1369 }
1370
1371 draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2],
1372 width, height,
1373 ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
1374 sv,
1375 num_sampler_view,
1376 st->passthrough_vs,
1377 driver_fp, fpv,
1378 ctx->Current.RasterColor,
1379 GL_FALSE, write_depth, write_stencil);
1380
1381 /* free the texture (but may persist in the cache) */
1382 pipe_resource_reference(&pt, NULL);
1383 }
1384
1385
1386
1387 /**
1388 * Software fallback for glCopyPixels(GL_STENCIL).
1389 */
1390 static void
copy_stencil_pixels(struct gl_context * ctx,GLint srcx,GLint srcy,GLsizei width,GLsizei height,GLint dstx,GLint dsty)1391 copy_stencil_pixels(struct gl_context *ctx, GLint srcx, GLint srcy,
1392 GLsizei width, GLsizei height,
1393 GLint dstx, GLint dsty)
1394 {
1395 struct gl_renderbuffer *rbDraw;
1396 struct pipe_context *pipe = st_context(ctx)->pipe;
1397 enum pipe_map_flags usage;
1398 struct pipe_transfer *ptDraw;
1399 uint8_t *drawMap;
1400 uint8_t *buffer;
1401 int i;
1402
1403 buffer = malloc(width * height * sizeof(uint8_t));
1404 if (!buffer) {
1405 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels(stencil)");
1406 return;
1407 }
1408
1409 /* Get the dest renderbuffer */
1410 rbDraw = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
1411
1412 /* this will do stencil pixel transfer ops */
1413 _mesa_readpixels(ctx, srcx, srcy, width, height,
1414 GL_STENCIL_INDEX, GL_UNSIGNED_BYTE,
1415 &ctx->DefaultPacking, buffer);
1416
1417 if (0) {
1418 /* debug code: dump stencil values */
1419 GLint row, col;
1420 for (row = 0; row < height; row++) {
1421 printf("%3d: ", row);
1422 for (col = 0; col < width; col++) {
1423 printf("%02x ", buffer[col + row * width]);
1424 }
1425 printf("\n");
1426 }
1427 }
1428
1429 if (_mesa_is_format_packed_depth_stencil(rbDraw->Format))
1430 usage = PIPE_MAP_READ_WRITE;
1431 else
1432 usage = PIPE_MAP_WRITE;
1433
1434 if (_mesa_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
1435 dsty = rbDraw->Height - dsty - height;
1436 }
1437
1438 assert(util_format_get_blockwidth(rbDraw->texture->format) == 1);
1439 assert(util_format_get_blockheight(rbDraw->texture->format) == 1);
1440
1441 /* map the stencil buffer */
1442 drawMap = pipe_texture_map(pipe,
1443 rbDraw->texture,
1444 rbDraw->surface->u.tex.level,
1445 rbDraw->surface->u.tex.first_layer,
1446 usage, dstx, dsty,
1447 width, height, &ptDraw);
1448
1449 /* draw */
1450 /* XXX PixelZoom not handled yet */
1451 for (i = 0; i < height; i++) {
1452 uint8_t *dst;
1453 const uint8_t *src;
1454 int y;
1455
1456 y = i;
1457
1458 if (_mesa_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
1459 y = height - y - 1;
1460 }
1461
1462 dst = drawMap + y * ptDraw->stride;
1463 src = buffer + i * width;
1464
1465 _mesa_pack_ubyte_stencil_row(rbDraw->Format, width, src, dst);
1466 }
1467
1468 free(buffer);
1469
1470 /* unmap the stencil buffer */
1471 pipe_texture_unmap(pipe, ptDraw);
1472 }
1473
1474
1475 /**
1476 * Return renderbuffer to use for reading color pixels for glCopyPixels
1477 */
1478 static struct gl_renderbuffer *
st_get_color_read_renderbuffer(struct gl_context * ctx)1479 st_get_color_read_renderbuffer(struct gl_context *ctx)
1480 {
1481 struct gl_framebuffer *fb = ctx->ReadBuffer;
1482 return fb->_ColorReadBuffer;
1483 }
1484
1485
1486 /**
1487 * Try to do a glCopyPixels for simple cases with a blit by calling
1488 * pipe->blit().
1489 *
1490 * We can do this when we're copying color pixels (depth/stencil
1491 * eventually) with no pixel zoom, no pixel transfer ops, no
1492 * per-fragment ops, and the src/dest regions don't overlap.
1493 */
1494 static GLboolean
blit_copy_pixels(struct gl_context * ctx,GLint srcx,GLint srcy,GLsizei width,GLsizei height,GLint dstx,GLint dsty,GLenum type)1495 blit_copy_pixels(struct gl_context *ctx, GLint srcx, GLint srcy,
1496 GLsizei width, GLsizei height,
1497 GLint dstx, GLint dsty, GLenum type)
1498 {
1499 struct st_context *st = st_context(ctx);
1500 struct pipe_context *pipe = st->pipe;
1501 struct pipe_screen *screen = st->screen;
1502 struct gl_pixelstore_attrib pack, unpack;
1503 GLint readX, readY, readW, readH, drawX, drawY, drawW, drawH;
1504
1505 if (type == GL_DEPTH_STENCIL_TO_RGBA_NV || type == GL_DEPTH_STENCIL_TO_BGRA_NV)
1506 return GL_FALSE;
1507
1508 if (ctx->Pixel.ZoomX == 1.0 &&
1509 ctx->Pixel.ZoomY == 1.0 &&
1510 (type != GL_COLOR ||
1511 (ctx->_ImageTransferState == 0x0 &&
1512 !ctx->Color.BlendEnabled &&
1513 !ctx->Color.AlphaEnabled &&
1514 (!ctx->Color.ColorLogicOpEnabled || ctx->Color.LogicOp == GL_COPY) &&
1515 !ctx->Depth.BoundsTest &&
1516 (!ctx->Depth.Test || (ctx->Depth.Func == GL_ALWAYS && !ctx->Depth.Mask)) &&
1517 !ctx->Fog.Enabled &&
1518 (!ctx->Stencil.Enabled ||
1519 (ctx->Stencil.FailFunc[0] == GL_KEEP &&
1520 ctx->Stencil.ZPassFunc[0] == GL_KEEP &&
1521 ctx->Stencil.ZFailFunc[0] == GL_KEEP)) &&
1522 !ctx->FragmentProgram.Enabled &&
1523 !ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT] &&
1524 !_mesa_ati_fragment_shader_enabled(ctx) &&
1525 ctx->DrawBuffer->_NumColorDrawBuffers == 1)) &&
1526 !ctx->Query.CurrentOcclusionObject) {
1527 struct gl_renderbuffer *rbRead, *rbDraw;
1528
1529 /*
1530 * Clip the read region against the src buffer bounds.
1531 * We'll still allocate a temporary buffer/texture for the original
1532 * src region size but we'll only read the region which is on-screen.
1533 * This may mean that we draw garbage pixels into the dest region, but
1534 * that's expected.
1535 */
1536 readX = srcx;
1537 readY = srcy;
1538 readW = width;
1539 readH = height;
1540 pack = ctx->DefaultPacking;
1541 if (!_mesa_clip_readpixels(ctx, &readX, &readY, &readW, &readH, &pack))
1542 return GL_TRUE; /* all done */
1543
1544 /* clip against dest buffer bounds and scissor box */
1545 drawX = dstx + pack.SkipPixels;
1546 drawY = dsty + pack.SkipRows;
1547 unpack = pack;
1548 if (!_mesa_clip_drawpixels(ctx, &drawX, &drawY, &readW, &readH, &unpack))
1549 return GL_TRUE; /* all done */
1550
1551 readX = readX - pack.SkipPixels + unpack.SkipPixels;
1552 readY = readY - pack.SkipRows + unpack.SkipRows;
1553
1554 drawW = readW;
1555 drawH = readH;
1556
1557 if (type == GL_COLOR) {
1558 rbRead = st_get_color_read_renderbuffer(ctx);
1559 rbDraw = ctx->DrawBuffer->_ColorDrawBuffers[0];
1560 } else if (type == GL_DEPTH || type == GL_DEPTH_STENCIL) {
1561 rbRead = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
1562 rbDraw = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
1563 } else if (type == GL_STENCIL) {
1564 rbRead = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
1565 rbDraw = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
1566 } else {
1567 return false;
1568 }
1569
1570 /* Flip src/dst position depending on the orientation of buffers. */
1571 if (_mesa_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
1572 readY = rbRead->Height - readY;
1573 readH = -readH;
1574 }
1575
1576 if (_mesa_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
1577 /* We can't flip the destination for pipe->blit, so we only adjust
1578 * its position and flip the source.
1579 */
1580 drawY = rbDraw->Height - drawY - drawH;
1581 readY += readH;
1582 readH = -readH;
1583 }
1584
1585 if (rbRead != rbDraw ||
1586 !_mesa_regions_overlap(readX, readY, readX + readW, readY + readH,
1587 drawX, drawY, drawX + drawW, drawY + drawH)) {
1588 struct pipe_blit_info blit;
1589
1590 memset(&blit, 0, sizeof(blit));
1591 blit.src.resource = rbRead->texture;
1592 blit.src.level = rbRead->surface->u.tex.level;
1593 blit.src.format = rbRead->texture->format;
1594 blit.src.box.x = readX;
1595 blit.src.box.y = readY;
1596 blit.src.box.z = rbRead->surface->u.tex.first_layer;
1597 blit.src.box.width = readW;
1598 blit.src.box.height = readH;
1599 blit.src.box.depth = 1;
1600 blit.dst.resource = rbDraw->texture;
1601 blit.dst.level = rbDraw->surface->u.tex.level;
1602 blit.dst.format = rbDraw->texture->format;
1603 blit.dst.box.x = drawX;
1604 blit.dst.box.y = drawY;
1605 blit.dst.box.z = rbDraw->surface->u.tex.first_layer;
1606 blit.dst.box.width = drawW;
1607 blit.dst.box.height = drawH;
1608 blit.dst.box.depth = 1;
1609 blit.filter = PIPE_TEX_FILTER_NEAREST;
1610 blit.render_condition_enable = ctx->Query.CondRenderQuery != NULL;
1611
1612 if (type == GL_COLOR)
1613 blit.mask |= PIPE_MASK_RGBA;
1614 if (type == GL_DEPTH)
1615 blit.mask |= PIPE_MASK_Z;
1616 if (type == GL_STENCIL)
1617 blit.mask |= PIPE_MASK_S;
1618 if (type == GL_DEPTH_STENCIL)
1619 blit.mask |= PIPE_MASK_ZS;
1620
1621 if (ctx->DrawBuffer != ctx->WinSysDrawBuffer)
1622 st_window_rectangles_to_blit(ctx, &blit);
1623
1624 if (screen->is_format_supported(screen, blit.src.format,
1625 blit.src.resource->target,
1626 blit.src.resource->nr_samples,
1627 blit.src.resource->nr_storage_samples,
1628 PIPE_BIND_SAMPLER_VIEW) &&
1629 screen->is_format_supported(screen, blit.dst.format,
1630 blit.dst.resource->target,
1631 blit.dst.resource->nr_samples,
1632 blit.dst.resource->nr_storage_samples,
1633 PIPE_BIND_RENDER_TARGET)) {
1634 pipe->blit(pipe, &blit);
1635 return GL_TRUE;
1636 }
1637 }
1638 }
1639
1640 return GL_FALSE;
1641 }
1642
1643 void
st_CopyPixels(struct gl_context * ctx,GLint srcx,GLint srcy,GLsizei width,GLsizei height,GLint dstx,GLint dsty,GLenum type)1644 st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
1645 GLsizei width, GLsizei height,
1646 GLint dstx, GLint dsty, GLenum type)
1647 {
1648 struct st_context *st = st_context(ctx);
1649 struct pipe_context *pipe = st->pipe;
1650 struct pipe_screen *screen = st->screen;
1651 struct gl_renderbuffer *rbRead;
1652 void *driver_fp;
1653 struct pipe_resource *pt;
1654 struct pipe_sampler_view *sv[2] = { NULL };
1655 struct st_fp_variant *fpv = NULL;
1656 int num_sampler_view = 1;
1657 enum pipe_format srcFormat;
1658 unsigned srcBind;
1659 GLboolean invertTex = GL_FALSE;
1660 GLint readX, readY, readW, readH;
1661 struct gl_pixelstore_attrib pack = ctx->DefaultPacking;
1662 GLboolean write_stencil = GL_FALSE;
1663 GLboolean write_depth = GL_FALSE;
1664
1665 _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer);
1666
1667 st_flush_bitmap_cache(st);
1668 st_invalidate_readpix_cache(st);
1669
1670 st_validate_state(st, ST_PIPELINE_META_STATE_MASK);
1671
1672 if (blit_copy_pixels(ctx, srcx, srcy, width, height, dstx, dsty, type))
1673 return;
1674
1675 /* fallback if the driver can't do stencil exports */
1676 if (type == GL_DEPTH_STENCIL &&
1677 !st->has_stencil_export) {
1678 st_CopyPixels(ctx, srcx, srcy, width, height, dstx, dsty, GL_STENCIL);
1679 st_CopyPixels(ctx, srcx, srcy, width, height, dstx, dsty, GL_DEPTH);
1680 return;
1681 }
1682
1683 /* fallback if the driver can't do stencil exports */
1684 if (type == GL_STENCIL &&
1685 !st->has_stencil_export) {
1686 copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty);
1687 return;
1688 }
1689
1690 /*
1691 * The subsequent code implements glCopyPixels by copying the source
1692 * pixels into a temporary texture that's then applied to a textured quad.
1693 * When we draw the textured quad, all the usual per-fragment operations
1694 * are handled.
1695 */
1696
1697 st_make_passthrough_vertex_shader(st);
1698
1699 /*
1700 * Get vertex/fragment shaders
1701 */
1702 if (type == GL_COLOR) {
1703 fpv = get_color_fp_variant(st);
1704
1705 rbRead = st_get_color_read_renderbuffer(ctx);
1706
1707 driver_fp = fpv->base.driver_shader;
1708
1709 if (ctx->Pixel.MapColorFlag) {
1710 pipe_sampler_view_reference(&sv[1],
1711 st->pixel_xfer.pixelmap_sampler_view);
1712 num_sampler_view++;
1713 }
1714
1715 /* compiling a new fragment shader variant added new state constants
1716 * into the constant buffer, we need to update them
1717 */
1718 st_upload_constants(st, ctx->FragmentProgram._Current, MESA_SHADER_FRAGMENT);
1719 } else if (type == GL_DEPTH) {
1720 rbRead = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
1721 driver_fp = get_drawpix_z_stencil_program(st, GL_TRUE, GL_FALSE);
1722 } else if (type == GL_STENCIL) {
1723 rbRead = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
1724 driver_fp = get_drawpix_z_stencil_program(st, GL_FALSE, GL_TRUE);
1725 } else if (type == GL_DEPTH_STENCIL) {
1726 rbRead = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
1727 driver_fp = get_drawpix_z_stencil_program(st, GL_TRUE, GL_TRUE);
1728 } else {
1729 assert(type == GL_DEPTH_STENCIL_TO_RGBA_NV || type == GL_DEPTH_STENCIL_TO_BGRA_NV);
1730 rbRead = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
1731 if (type == GL_DEPTH_STENCIL_TO_RGBA_NV)
1732 driver_fp = get_drawpix_zs_to_color_program(st, GL_TRUE);
1733 else
1734 driver_fp = get_drawpix_zs_to_color_program(st, GL_FALSE);
1735 if (!driver_fp) {
1736 assert(0 && "operation not supported by CopyPixels implemetation");
1737 return;
1738 }
1739 }
1740
1741
1742 /* Choose the format for the temporary texture. */
1743 srcFormat = rbRead->texture->format;
1744 srcBind = PIPE_BIND_SAMPLER_VIEW |
1745 (type == GL_COLOR ? PIPE_BIND_RENDER_TARGET : PIPE_BIND_DEPTH_STENCIL);
1746
1747 if (!screen->is_format_supported(screen, srcFormat, st->internal_target, 0,
1748 0, srcBind)) {
1749 /* srcFormat is non-renderable. Find a compatible renderable format. */
1750 if (type == GL_DEPTH) {
1751 srcFormat = st_choose_format(st, GL_DEPTH_COMPONENT, GL_NONE,
1752 GL_NONE, st->internal_target, 0, 0,
1753 srcBind, false, false);
1754 }
1755 else if (type == GL_STENCIL) {
1756 /* can't use texturing, fallback to copy */
1757 copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty);
1758 return;
1759 }
1760 else {
1761 assert(type == GL_COLOR);
1762
1763 if (util_format_is_float(srcFormat)) {
1764 srcFormat = st_choose_format(st, GL_RGBA32F, GL_NONE,
1765 GL_NONE, st->internal_target, 0, 0,
1766 srcBind, false, false);
1767 }
1768 else if (util_format_is_pure_sint(srcFormat)) {
1769 srcFormat = st_choose_format(st, GL_RGBA32I, GL_NONE,
1770 GL_NONE, st->internal_target, 0, 0,
1771 srcBind, false, false);
1772 }
1773 else if (util_format_is_pure_uint(srcFormat)) {
1774 srcFormat = st_choose_format(st, GL_RGBA32UI, GL_NONE,
1775 GL_NONE, st->internal_target, 0, 0,
1776 srcBind, false, false);
1777 }
1778 else if (util_format_is_snorm(srcFormat)) {
1779 srcFormat = st_choose_format(st, GL_RGBA16_SNORM, GL_NONE,
1780 GL_NONE, st->internal_target, 0, 0,
1781 srcBind, false, false);
1782 }
1783 else {
1784 srcFormat = st_choose_format(st, GL_RGBA, GL_NONE,
1785 GL_NONE, st->internal_target, 0, 0,
1786 srcBind, false, false);
1787 }
1788 }
1789
1790 if (srcFormat == PIPE_FORMAT_NONE) {
1791 assert(0 && "cannot choose a format for src of CopyPixels");
1792 return;
1793 }
1794 }
1795
1796 /* Invert src region if needed */
1797 if (_mesa_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
1798 srcy = ctx->ReadBuffer->Height - srcy - height;
1799 invertTex = !invertTex;
1800 }
1801
1802 /* Clip the read region against the src buffer bounds.
1803 * We'll still allocate a temporary buffer/texture for the original
1804 * src region size but we'll only read the region which is on-screen.
1805 * This may mean that we draw garbage pixels into the dest region, but
1806 * that's expected.
1807 */
1808 readX = srcx;
1809 readY = srcy;
1810 readW = width;
1811 readH = height;
1812 if (!_mesa_clip_readpixels(ctx, &readX, &readY, &readW, &readH, &pack)) {
1813 /* The source region is completely out of bounds. Do nothing.
1814 * The GL spec says "Results of copies from outside the window,
1815 * or from regions of the window that are not exposed, are
1816 * hardware dependent and undefined."
1817 */
1818 return;
1819 }
1820
1821 readW = MAX2(0, readW);
1822 readH = MAX2(0, readH);
1823
1824 /* Allocate the temporary texture. */
1825 pt = alloc_texture(st, width, height, srcFormat, srcBind);
1826 if (!pt)
1827 return;
1828
1829 sv[0] = st_create_texture_sampler_view(st->pipe, pt);
1830 if (!sv[0]) {
1831 pipe_resource_reference(&pt, NULL);
1832 return;
1833 }
1834
1835 /* Create a second sampler view to read stencil */
1836 if (type == GL_STENCIL || type == GL_DEPTH_STENCIL ||
1837 type == GL_DEPTH_STENCIL_TO_RGBA_NV || type == GL_DEPTH_STENCIL_TO_BGRA_NV) {
1838 write_stencil = GL_TRUE;
1839 if (type == GL_DEPTH_STENCIL)
1840 write_depth = GL_TRUE;
1841 if (type == GL_DEPTH_STENCIL_TO_RGBA_NV || type == GL_DEPTH_STENCIL_TO_BGRA_NV) {
1842 write_depth = false;
1843 write_stencil = false;
1844 }
1845
1846 enum pipe_format stencil_format =
1847 util_format_stencil_only(pt->format);
1848 /* we should not be doing pixel map/transfer (see above) */
1849 assert(num_sampler_view == 1);
1850 sv[1] = st_create_texture_sampler_view_format(st->pipe, pt,
1851 stencil_format);
1852 if (!sv[1]) {
1853 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels");
1854 pipe_resource_reference(&pt, NULL);
1855 pipe_sampler_view_reference(&sv[0], NULL);
1856 return;
1857 }
1858 num_sampler_view++;
1859 }
1860 /* Copy the src region to the temporary texture. */
1861 {
1862 struct pipe_blit_info blit;
1863
1864 memset(&blit, 0, sizeof(blit));
1865 blit.src.resource = rbRead->texture;
1866 blit.src.level = rbRead->surface->u.tex.level;
1867 blit.src.format = rbRead->texture->format;
1868 blit.src.box.x = readX;
1869 blit.src.box.y = readY;
1870 blit.src.box.z = rbRead->surface->u.tex.first_layer;
1871 blit.src.box.width = readW;
1872 blit.src.box.height = readH;
1873 blit.src.box.depth = 1;
1874 blit.dst.resource = pt;
1875 blit.dst.level = 0;
1876 blit.dst.format = pt->format;
1877 blit.dst.box.x = pack.SkipPixels;
1878 blit.dst.box.y = pack.SkipRows;
1879 blit.dst.box.z = 0;
1880 blit.dst.box.width = readW;
1881 blit.dst.box.height = readH;
1882 blit.dst.box.depth = 1;
1883 if (type == GL_DEPTH)
1884 blit.mask = util_format_get_mask(pt->format) & ~PIPE_MASK_S;
1885 else if (type == GL_STENCIL)
1886 blit.mask = util_format_get_mask(pt->format) & ~PIPE_MASK_Z;
1887 else
1888 blit.mask = util_format_get_mask(pt->format);
1889 blit.filter = PIPE_TEX_FILTER_NEAREST;
1890
1891 pipe->blit(pipe, &blit);
1892 }
1893
1894 /* OK, the texture 'pt' contains the src image/pixels. Now draw a
1895 * textured quad with that texture.
1896 */
1897
1898 draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2],
1899 width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
1900 sv,
1901 num_sampler_view,
1902 st->passthrough_vs,
1903 driver_fp, fpv,
1904 ctx->Current.Attrib[VERT_ATTRIB_COLOR0],
1905 invertTex, write_depth, write_stencil);
1906
1907 pipe_resource_reference(&pt, NULL);
1908 }
1909
1910 void
st_destroy_drawpix(struct st_context * st)1911 st_destroy_drawpix(struct st_context *st)
1912 {
1913 GLuint i;
1914
1915 for (i = 0; i < ARRAY_SIZE(st->drawpix.zs_shaders); i++) {
1916 if (st->drawpix.zs_shaders[i])
1917 st->pipe->delete_fs_state(st->pipe, st->drawpix.zs_shaders[i]);
1918 }
1919
1920 if (st->passthrough_vs)
1921 st->pipe->delete_vs_state(st->pipe, st->passthrough_vs);
1922
1923 /* Free cache data */
1924 for (i = 0; i < ARRAY_SIZE(st->drawpix_cache.entries); i++) {
1925 struct drawpix_cache_entry *entry = &st->drawpix_cache.entries[i];
1926 free(entry->image);
1927 pipe_resource_reference(&entry->texture, NULL);
1928 }
1929 }
1930