Merge branch 'gallium-texture-transfer'
[mesa.git] / src / mesa / state_tracker / st_cb_drawpixels.c
1 /**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
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 TUNGSTEN GRAPHICS 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/imports.h"
34 #include "main/image.h"
35 #include "main/bufferobj.h"
36 #include "main/macros.h"
37 #include "main/texformat.h"
38 #include "main/state.h"
39 #include "shader/program.h"
40 #include "shader/prog_parameter.h"
41 #include "shader/prog_print.h"
42
43 #include "st_context.h"
44 #include "st_atom.h"
45 #include "st_atom_constbuf.h"
46 #include "st_draw.h"
47 #include "st_program.h"
48 #include "st_cb_drawpixels.h"
49 #include "st_cb_readpixels.h"
50 #include "st_cb_fbo.h"
51 #include "st_cb_texture.h"
52 #include "st_draw.h"
53 #include "st_format.h"
54 #include "st_mesa_to_tgsi.h"
55 #include "st_texture.h"
56 #include "pipe/p_context.h"
57 #include "pipe/p_defines.h"
58 #include "pipe/p_inlines.h"
59 #include "util/u_tile.h"
60 #include "util/u_draw_quad.h"
61 #include "shader/prog_instruction.h"
62 #include "cso_cache/cso_context.h"
63
64
65 /**
66 * Check if the given program is:
67 * 0: MOVE result.color, fragment.color;
68 * 1: END;
69 */
70 static GLboolean
71 is_passthrough_program(const struct gl_fragment_program *prog)
72 {
73 if (prog->Base.NumInstructions == 2) {
74 const struct prog_instruction *inst = prog->Base.Instructions;
75 if (inst[0].Opcode == OPCODE_MOV &&
76 inst[1].Opcode == OPCODE_END &&
77 inst[0].DstReg.File == PROGRAM_OUTPUT &&
78 inst[0].DstReg.Index == FRAG_RESULT_COLR &&
79 inst[0].DstReg.WriteMask == WRITEMASK_XYZW &&
80 inst[0].SrcReg[0].File == PROGRAM_INPUT &&
81 inst[0].SrcReg[0].Index == FRAG_ATTRIB_COL0 &&
82 inst[0].SrcReg[0].Swizzle == SWIZZLE_XYZW) {
83 return GL_TRUE;
84 }
85 }
86 return GL_FALSE;
87 }
88
89
90
91 /**
92 * Make fragment shader for glDraw/CopyPixels. This shader is made
93 * by combining the pixel transfer shader with the user-defined shader.
94 */
95 static struct st_fragment_program *
96 combined_drawpix_fragment_program(GLcontext *ctx)
97 {
98 struct st_context *st = ctx->st;
99 struct st_fragment_program *stfp;
100
101 if (st->pixel_xfer.program->serialNo == st->pixel_xfer.xfer_prog_sn
102 && st->fp->serialNo == st->pixel_xfer.user_prog_sn) {
103 /* the pixel tranfer program has not changed and the user-defined
104 * program has not changed, so re-use the combined program.
105 */
106 stfp = st->pixel_xfer.combined_prog;
107 }
108 else {
109 /* Concatenate the pixel transfer program with the current user-
110 * defined program.
111 */
112 if (is_passthrough_program(&st->fp->Base)) {
113 stfp = (struct st_fragment_program *)
114 _mesa_clone_program(ctx, &st->pixel_xfer.program->Base.Base);
115 }
116 else {
117 #if 0
118 printf("Base program:\n");
119 _mesa_print_program(&st->fp->Base.Base);
120 printf("DrawPix program:\n");
121 _mesa_print_program(&st->pixel_xfer.program->Base.Base);
122 #endif
123 stfp = (struct st_fragment_program *)
124 _mesa_combine_programs(ctx,
125 &st->pixel_xfer.program->Base.Base,
126 &st->fp->Base.Base);
127 }
128
129 #if 0
130 {
131 struct gl_program *p = &stfp->Base.Base;
132 printf("Combined DrawPixels program:\n");
133 _mesa_print_program(p);
134 printf("InputsRead: 0x%x\n", p->InputsRead);
135 printf("OutputsWritten: 0x%x\n", p->OutputsWritten);
136 _mesa_print_parameter_list(p->Parameters);
137 }
138 #endif
139
140 /* translate to TGSI tokens */
141 st_translate_fragment_program(st, stfp, NULL);
142
143 /* save new program, update serial numbers */
144 st->pixel_xfer.xfer_prog_sn = st->pixel_xfer.program->serialNo;
145 st->pixel_xfer.user_prog_sn = st->fp->serialNo;
146 st->pixel_xfer.combined_prog_sn = stfp->serialNo;
147 st->pixel_xfer.combined_prog = stfp;
148 }
149
150 /* Ideally we'd have updated the pipe constants during the normal
151 * st/atom mechanism. But we can't since this is specific to glDrawPixels.
152 */
153 st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT);
154
155 return stfp;
156 }
157
158
159 /**
160 * Create fragment shader that does a TEX() instruction to get a Z
161 * value, then writes to FRAG_RESULT_DEPR.
162 * Pass fragment color through as-is.
163 */
164 static struct st_fragment_program *
165 make_fragment_shader_z(struct st_context *st)
166 {
167 GLcontext *ctx = st->ctx;
168 struct gl_program *p;
169 GLuint ic = 0;
170
171 if (st->drawpix.z_shader) {
172 return st->drawpix.z_shader;
173 }
174
175 /*
176 * Create shader now
177 */
178 p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
179 if (!p)
180 return NULL;
181
182 p->NumInstructions = 3;
183
184 p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
185 if (!p->Instructions) {
186 ctx->Driver.DeleteProgram(ctx, p);
187 return NULL;
188 }
189 _mesa_init_instructions(p->Instructions, p->NumInstructions);
190
191 /* TEX result.depth, fragment.texcoord[0], texture[0], 2D; */
192 p->Instructions[ic].Opcode = OPCODE_TEX;
193 p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
194 p->Instructions[ic].DstReg.Index = FRAG_RESULT_DEPR;
195 p->Instructions[ic].DstReg.WriteMask = WRITEMASK_Z;
196 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
197 p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
198 p->Instructions[ic].TexSrcUnit = 0;
199 p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
200 ic++;
201
202 /* MOV result.color, fragment.color */
203 p->Instructions[ic].Opcode = OPCODE_MOV;
204 p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
205 p->Instructions[ic].DstReg.Index = FRAG_RESULT_COLR;
206 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
207 p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_COL0;
208 ic++;
209
210 /* END; */
211 p->Instructions[ic++].Opcode = OPCODE_END;
212
213 assert(ic == p->NumInstructions);
214
215 p->InputsRead = FRAG_BIT_TEX0 | FRAG_BIT_COL0;
216 p->OutputsWritten = (1 << FRAG_RESULT_COLR) | (1 << FRAG_RESULT_DEPR);
217 p->SamplersUsed = 0x1; /* sampler 0 (bit 0) is used */
218
219 st->drawpix.z_shader = (struct st_fragment_program *) p;
220 st_translate_fragment_program(st, st->drawpix.z_shader, NULL);
221
222 return st->drawpix.z_shader;
223 }
224
225
226
227 /**
228 * Create a simple vertex shader that just passes through the
229 * vertex position and texcoord (and optionally, color).
230 */
231 static struct st_vertex_program *
232 st_make_passthrough_vertex_shader(struct st_context *st, GLboolean passColor)
233 {
234 GLcontext *ctx = st->ctx;
235 struct st_vertex_program *stvp;
236 struct gl_program *p;
237 GLuint ic = 0;
238
239 if (st->drawpix.vert_shaders[passColor])
240 return st->drawpix.vert_shaders[passColor];
241
242 /*
243 * Create shader now
244 */
245 p = ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
246 if (!p)
247 return NULL;
248
249 if (passColor)
250 p->NumInstructions = 4;
251 else
252 p->NumInstructions = 3;
253
254 p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
255 if (!p->Instructions) {
256 ctx->Driver.DeleteProgram(ctx, p);
257 return NULL;
258 }
259 _mesa_init_instructions(p->Instructions, p->NumInstructions);
260 /* MOV result.pos, vertex.pos; */
261 p->Instructions[0].Opcode = OPCODE_MOV;
262 p->Instructions[0].DstReg.File = PROGRAM_OUTPUT;
263 p->Instructions[0].DstReg.Index = VERT_RESULT_HPOS;
264 p->Instructions[0].SrcReg[0].File = PROGRAM_INPUT;
265 p->Instructions[0].SrcReg[0].Index = VERT_ATTRIB_POS;
266 /* MOV result.texcoord0, vertex.texcoord0; */
267 p->Instructions[1].Opcode = OPCODE_MOV;
268 p->Instructions[1].DstReg.File = PROGRAM_OUTPUT;
269 p->Instructions[1].DstReg.Index = VERT_RESULT_TEX0;
270 p->Instructions[1].SrcReg[0].File = PROGRAM_INPUT;
271 p->Instructions[1].SrcReg[0].Index = VERT_ATTRIB_TEX0;
272 ic = 2;
273 if (passColor) {
274 /* MOV result.color0, vertex.color0; */
275 p->Instructions[ic].Opcode = OPCODE_MOV;
276 p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
277 p->Instructions[ic].DstReg.Index = VERT_RESULT_COL0;
278 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
279 p->Instructions[ic].SrcReg[0].Index = VERT_ATTRIB_COLOR0;
280 ic++;
281 }
282
283 /* END; */
284 p->Instructions[ic].Opcode = OPCODE_END;
285 ic++;
286
287 assert(ic == p->NumInstructions);
288
289 p->InputsRead = VERT_BIT_POS | VERT_BIT_TEX0;
290 p->OutputsWritten = ((1 << VERT_RESULT_TEX0) |
291 (1 << VERT_RESULT_HPOS));
292 if (passColor) {
293 p->InputsRead |= VERT_BIT_COLOR0;
294 p->OutputsWritten |= (1 << VERT_RESULT_COL0);
295 }
296
297 stvp = (struct st_vertex_program *) p;
298 st_translate_vertex_program(st, stvp, NULL, NULL, NULL);
299
300 st->drawpix.vert_shaders[passColor] = stvp;
301
302 return stvp;
303 }
304
305
306 static GLenum
307 _mesa_base_format(GLenum format)
308 {
309 switch (format) {
310 case GL_DEPTH_COMPONENT:
311 return GL_DEPTH_COMPONENT;
312 case GL_STENCIL_INDEX:
313 return GL_STENCIL_INDEX;
314 default:
315 return GL_RGBA;
316 }
317 }
318
319
320 /**
321 * Make texture containing an image for glDrawPixels image.
322 * If 'pixels' is NULL, leave the texture image data undefined.
323 */
324 static struct pipe_texture *
325 make_texture(struct st_context *st,
326 GLsizei width, GLsizei height, GLenum format, GLenum type,
327 const struct gl_pixelstore_attrib *unpack,
328 const GLvoid *pixels)
329 {
330 GLcontext *ctx = st->ctx;
331 struct pipe_context *pipe = st->pipe;
332 struct pipe_screen *screen = pipe->screen;
333 const struct gl_texture_format *mformat;
334 struct pipe_texture *pt;
335 enum pipe_format pipeFormat;
336 GLuint cpp;
337 GLenum baseFormat;
338
339 baseFormat = _mesa_base_format(format);
340
341 mformat = st_ChooseTextureFormat(ctx, baseFormat, format, type);
342 assert(mformat);
343
344 pipeFormat = st_mesa_format_to_pipe_format(mformat->MesaFormat);
345 assert(pipeFormat);
346 cpp = st_sizeof_format(pipeFormat);
347
348 pixels = _mesa_map_drawpix_pbo(ctx, unpack, pixels);
349 if (!pixels)
350 return NULL;
351
352 pt = st_texture_create(st, PIPE_TEXTURE_2D, pipeFormat, 0, width, height,
353 1, 0,
354 PIPE_TEXTURE_USAGE_SAMPLER);
355 if (!pt) {
356 _mesa_unmap_drawpix_pbo(ctx, unpack);
357 return NULL;
358 }
359
360 {
361 struct pipe_transfer *transfer;
362 static const GLuint dstImageOffsets = 0;
363 GLboolean success;
364 GLubyte *dest;
365 const GLbitfield imageTransferStateSave = ctx->_ImageTransferState;
366
367 /* we'll do pixel transfer in a fragment shader */
368 ctx->_ImageTransferState = 0x0;
369
370 transfer = screen->get_tex_transfer(screen, pt, 0, 0, 0,
371 PIPE_TRANSFER_WRITE, 0, 0,
372 width, height);
373
374 /* map texture transfer */
375 dest = screen->transfer_map(screen, transfer);
376
377 /* Put image into texture transfer.
378 * Note that the image is actually going to be upside down in
379 * the texture. We deal with that with texcoords.
380 */
381 success = mformat->StoreImage(ctx, 2, /* dims */
382 baseFormat, /* baseInternalFormat */
383 mformat, /* gl_texture_format */
384 dest, /* dest */
385 0, 0, 0, /* dstX/Y/Zoffset */
386 transfer->stride, /* dstRowStride, bytes */
387 &dstImageOffsets, /* dstImageOffsets */
388 width, height, 1, /* size */
389 format, type, /* src format/type */
390 pixels, /* data source */
391 unpack);
392
393 /* unmap */
394 screen->transfer_unmap(screen, transfer);
395 screen->tex_transfer_release(screen, &transfer);
396
397 assert(success);
398
399 /* restore */
400 ctx->_ImageTransferState = imageTransferStateSave;
401 }
402
403 _mesa_unmap_drawpix_pbo(ctx, unpack);
404
405 return pt;
406 }
407
408
409 /**
410 * Draw quad with texcoords and optional color.
411 * Coords are window coords with y=0=bottom.
412 * \param color may be null
413 * \param invertTex if true, flip texcoords vertically
414 */
415 static void
416 draw_quad(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z,
417 GLfloat x1, GLfloat y1, const GLfloat *color,
418 GLboolean invertTex)
419 {
420 struct st_context *st = ctx->st;
421 struct pipe_context *pipe = ctx->st->pipe;
422 GLfloat verts[4][3][4]; /* four verts, three attribs, XYZW */
423
424 /* setup vertex data */
425 {
426 const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
427 const GLfloat fb_width = (GLfloat) fb->Width;
428 const GLfloat fb_height = (GLfloat) fb->Height;
429 const GLfloat clip_x0 = x0 / fb_width * 2.0f - 1.0f;
430 const GLfloat clip_y0 = y0 / fb_height * 2.0f - 1.0f;
431 const GLfloat clip_x1 = x1 / fb_width * 2.0f - 1.0f;
432 const GLfloat clip_y1 = y1 / fb_height * 2.0f - 1.0f;
433 const GLfloat sLeft = 0.0f, sRight = 1.0f;
434 const GLfloat tTop = invertTex, tBot = 1.0f - tTop;
435 GLuint tex, i;
436
437 /* upper-left */
438 verts[0][0][0] = clip_x0; /* v[0].attr[0].x */
439 verts[0][0][1] = clip_y0; /* v[0].attr[0].y */
440
441 /* upper-right */
442 verts[1][0][0] = clip_x1;
443 verts[1][0][1] = clip_y0;
444
445 /* lower-right */
446 verts[2][0][0] = clip_x1;
447 verts[2][0][1] = clip_y1;
448
449 /* lower-left */
450 verts[3][0][0] = clip_x0;
451 verts[3][0][1] = clip_y1;
452
453 tex = color ? 2 : 1;
454 verts[0][tex][0] = sLeft; /* v[0].attr[tex].s */
455 verts[0][tex][1] = tTop; /* v[0].attr[tex].t */
456 verts[1][tex][0] = sRight;
457 verts[1][tex][1] = tTop;
458 verts[2][tex][0] = sRight;
459 verts[2][tex][1] = tBot;
460 verts[3][tex][0] = sLeft;
461 verts[3][tex][1] = tBot;
462
463 /* same for all verts: */
464 if (color) {
465 for (i = 0; i < 4; i++) {
466 verts[i][0][2] = z; /*Z*/
467 verts[i][0][3] = 1.0f; /*W*/
468 verts[i][1][0] = color[0];
469 verts[i][1][1] = color[1];
470 verts[i][1][2] = color[2];
471 verts[i][1][3] = color[3];
472 verts[i][2][2] = 0.0f; /*R*/
473 verts[i][2][3] = 1.0f; /*Q*/
474 }
475 }
476 else {
477 for (i = 0; i < 4; i++) {
478 verts[i][0][2] = z; /*Z*/
479 verts[i][0][3] = 1.0f; /*W*/
480 verts[i][1][2] = 0.0f; /*R*/
481 verts[i][1][3] = 1.0f; /*Q*/
482 }
483 }
484 }
485
486 {
487 struct pipe_buffer *buf;
488 ubyte *map;
489
490 /* allocate/load buffer object with vertex data */
491 buf = pipe_buffer_create(pipe->screen, 32, PIPE_BUFFER_USAGE_VERTEX,
492 sizeof(verts));
493 map = pipe_buffer_map(pipe->screen, buf, PIPE_BUFFER_USAGE_CPU_WRITE);
494 memcpy(map, verts, sizeof(verts));
495 pipe_buffer_unmap(pipe->screen, buf);
496
497 util_draw_vertex_buffer(pipe, buf, 0,
498 PIPE_PRIM_QUADS,
499 4, /* verts */
500 3); /* attribs/vert */
501 pipe_buffer_reference(pipe->screen, &buf, NULL);
502 }
503 }
504
505
506
507 static void
508 draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
509 GLsizei width, GLsizei height,
510 GLfloat zoomX, GLfloat zoomY,
511 struct pipe_texture *pt,
512 struct st_vertex_program *stvp,
513 struct st_fragment_program *stfp,
514 const GLfloat *color,
515 GLboolean invertTex)
516 {
517 struct st_context *st = ctx->st;
518 struct pipe_context *pipe = ctx->st->pipe;
519 struct cso_context *cso = ctx->st->cso_context;
520 GLfloat x0, y0, x1, y1;
521 GLsizei maxSize;
522
523 /* limit checks */
524 /* XXX if DrawPixels image is larger than max texture size, break
525 * it up into chunks.
526 */
527 maxSize = 1 << (pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
528 assert(width <= maxSize);
529 assert(height <= maxSize);
530
531 cso_save_rasterizer(cso);
532 cso_save_viewport(cso);
533 cso_save_samplers(cso);
534 cso_save_sampler_textures(cso);
535 cso_save_fragment_shader(cso);
536 cso_save_vertex_shader(cso);
537
538 /* rasterizer state: just scissor */
539 {
540 struct pipe_rasterizer_state rasterizer;
541 memset(&rasterizer, 0, sizeof(rasterizer));
542 rasterizer.gl_rasterization_rules = 1;
543 rasterizer.scissor = ctx->Scissor.Enabled;
544 cso_set_rasterizer(cso, &rasterizer);
545 }
546
547 /* fragment shader state: TEX lookup program */
548 cso_set_fragment_shader_handle(cso, stfp->driver_shader);
549
550 /* vertex shader state: position + texcoord pass-through */
551 cso_set_vertex_shader_handle(cso, stvp->driver_shader);
552
553
554 /* texture sampling state: */
555 {
556 struct pipe_sampler_state sampler;
557 memset(&sampler, 0, sizeof(sampler));
558 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP;
559 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP;
560 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP;
561 sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
562 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
563 sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
564 sampler.normalized_coords = 1;
565
566 cso_single_sampler(cso, 0, &sampler);
567 if (st->pixel_xfer.pixelmap_enabled) {
568 cso_single_sampler(cso, 1, &sampler);
569 }
570 cso_single_sampler_done(cso);
571 }
572
573 /* viewport state: viewport matching window dims */
574 {
575 const float width = (float) ctx->DrawBuffer->Width;
576 const float height = (float) ctx->DrawBuffer->Height;
577 struct pipe_viewport_state vp;
578 vp.scale[0] = 0.5f * width;
579 vp.scale[1] = -0.5f * height;
580 vp.scale[2] = 1.0f;
581 vp.scale[3] = 1.0f;
582 vp.translate[0] = 0.5f * width;
583 vp.translate[1] = 0.5f * height;
584 vp.translate[2] = 0.0f;
585 vp.translate[3] = 0.0f;
586 cso_set_viewport(cso, &vp);
587 }
588
589 /* texture state: */
590 if (st->pixel_xfer.pixelmap_enabled) {
591 struct pipe_texture *textures[2];
592 textures[0] = pt;
593 textures[1] = st->pixel_xfer.pixelmap_texture;
594 pipe->set_sampler_textures(pipe, 2, textures);
595 }
596 else {
597 pipe->set_sampler_textures(pipe, 1, &pt);
598 }
599
600 /* Compute window coords (y=0=bottom) with pixel zoom.
601 * Recall that these coords are transformed by the current
602 * vertex shader and viewport transformation.
603 */
604 x0 = (GLfloat) x;
605 x1 = x + width * ctx->Pixel.ZoomX;
606 y0 = (GLfloat) y;
607 y1 = y + height * ctx->Pixel.ZoomY;
608 //if(!color)
609 draw_quad(ctx, x0, y0, z, x1, y1, color, invertTex);
610 //else
611 //printf("skip draw quad\n");
612 /* restore state */
613 cso_restore_rasterizer(cso);
614 cso_restore_viewport(cso);
615 cso_restore_samplers(cso);
616 cso_restore_sampler_textures(cso);
617 cso_restore_fragment_shader(cso);
618 cso_restore_vertex_shader(cso);
619 }
620
621
622 /**
623 * Check if a GL format/type combination is a match to the given pipe format.
624 * XXX probably move this to a re-usable place.
625 */
626 static GLboolean
627 compatible_formats(GLenum format, GLenum type, enum pipe_format pipeFormat)
628 {
629 static const GLuint one = 1;
630 GLubyte littleEndian = *((GLubyte *) &one);
631
632 if (pipeFormat == PIPE_FORMAT_R8G8B8A8_UNORM &&
633 format == GL_RGBA &&
634 type == GL_UNSIGNED_BYTE &&
635 !littleEndian) {
636 return GL_TRUE;
637 }
638 else if (pipeFormat == PIPE_FORMAT_R8G8B8A8_UNORM &&
639 format == GL_ABGR_EXT &&
640 type == GL_UNSIGNED_BYTE &&
641 littleEndian) {
642 return GL_TRUE;
643 }
644 else if (pipeFormat == PIPE_FORMAT_A8R8G8B8_UNORM &&
645 format == GL_BGRA &&
646 type == GL_UNSIGNED_BYTE &&
647 littleEndian) {
648 return GL_TRUE;
649 }
650 else if (pipeFormat == PIPE_FORMAT_R5G6B5_UNORM &&
651 format == GL_RGB &&
652 type == GL_UNSIGNED_SHORT_5_6_5) {
653 /* endian don't care */
654 return GL_TRUE;
655 }
656 else if (pipeFormat == PIPE_FORMAT_R5G6B5_UNORM &&
657 format == GL_BGR &&
658 type == GL_UNSIGNED_SHORT_5_6_5_REV) {
659 /* endian don't care */
660 return GL_TRUE;
661 }
662 else if (pipeFormat == PIPE_FORMAT_S8_UNORM &&
663 format == GL_STENCIL_INDEX &&
664 type == GL_UNSIGNED_BYTE) {
665 return GL_TRUE;
666 }
667 else if (pipeFormat == PIPE_FORMAT_Z32_UNORM &&
668 format == GL_DEPTH_COMPONENT &&
669 type == GL_UNSIGNED_INT) {
670 return GL_TRUE;
671 }
672 /* XXX add more cases */
673 else {
674 return GL_FALSE;
675 }
676 }
677
678
679 /**
680 * Check if any per-fragment ops are enabled.
681 * XXX probably move this to a re-usable place.
682 */
683 static GLboolean
684 any_fragment_ops(const struct st_context *st)
685 {
686 if (st->state.depth_stencil.alpha.enabled ||
687 st->state.depth_stencil.depth.enabled ||
688 st->state.blend.blend_enable ||
689 st->state.blend.logicop_enable)
690 /* XXX more checks */
691 return GL_TRUE;
692 else
693 return GL_FALSE;
694 }
695
696
697 /**
698 * Check if any pixel transfer ops are enabled.
699 * XXX probably move this to a re-usable place.
700 */
701 static GLboolean
702 any_pixel_transfer_ops(const struct st_context *st)
703 {
704 if (st->ctx->Pixel.RedScale != 1.0 ||
705 st->ctx->Pixel.RedBias != 0.0 ||
706 st->ctx->Pixel.GreenScale != 1.0 ||
707 st->ctx->Pixel.GreenBias != 0.0 ||
708 st->ctx->Pixel.BlueScale != 1.0 ||
709 st->ctx->Pixel.BlueBias != 0.0 ||
710 st->ctx->Pixel.AlphaScale != 1.0 ||
711 st->ctx->Pixel.AlphaBias != 0.0 ||
712 st->ctx->Pixel.MapColorFlag)
713 /* XXX more checks */
714 return GL_TRUE;
715 else
716 return GL_FALSE;
717 }
718
719
720 /**
721 * Draw image with a blit, or other non-textured quad method.
722 */
723 static void
724 draw_blit(struct st_context *st,
725 GLsizei width, GLsizei height,
726 GLenum format, GLenum type, const GLvoid *pixels)
727 {
728
729
730 }
731
732
733 static void
734 draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
735 GLsizei width, GLsizei height, GLenum type,
736 const struct gl_pixelstore_attrib *unpack,
737 const GLvoid *pixels)
738 {
739 struct st_context *st = ctx->st;
740 struct pipe_context *pipe = st->pipe;
741 struct pipe_screen *screen = pipe->screen;
742 struct st_renderbuffer *strb;
743 struct pipe_transfer *pt;
744 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
745 GLint skipPixels;
746 ubyte *stmap;
747
748 pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
749
750 strb = st_renderbuffer(ctx->DrawBuffer->
751 Attachment[BUFFER_STENCIL].Renderbuffer);
752 pt = screen->get_tex_transfer(screen, strb->texture, 0, 0, 0,
753 PIPE_TRANSFER_WRITE, x, y,
754 width, height);
755
756 stmap = screen->transfer_map(screen, pt);
757
758 /* if width > MAX_WIDTH, have to process image in chunks */
759 skipPixels = 0;
760 while (skipPixels < width) {
761 const GLint spanX = skipPixels;
762 const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
763 GLint row;
764 for (row = 0; row < height; row++) {
765 GLint spanY = row;
766 GLubyte values[MAX_WIDTH];
767 GLenum destType = GL_UNSIGNED_BYTE;
768 const GLvoid *source = _mesa_image_address2d(unpack, pixels,
769 width, height,
770 GL_COLOR_INDEX, type,
771 row, skipPixels);
772 _mesa_unpack_stencil_span(ctx, spanWidth, destType, values,
773 type, source, unpack,
774 ctx->_ImageTransferState);
775 if (zoom) {
776 /*
777 _swrast_write_zoomed_stencil_span(ctx, 0, 0, spanWidth,
778 spanX, spanY, values);
779 */
780 }
781 else {
782 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
783 spanY = height - spanY - 1;
784 }
785
786 switch (pt->format) {
787 case PIPE_FORMAT_S8_UNORM:
788 {
789 ubyte *dest = stmap + spanY * pt->stride + spanX;
790 memcpy(dest, values, spanWidth);
791 }
792 break;
793 case PIPE_FORMAT_S8Z24_UNORM:
794 {
795 uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4);
796 GLint k;
797 for (k = 0; k < spanWidth; k++) {
798 uint p = dest[k];
799 p = (p & 0xffffff) | (values[k] << 24);
800 dest[k] = p;
801 }
802 }
803 break;
804 default:
805 assert(0);
806 }
807 }
808 }
809 skipPixels += spanWidth;
810 }
811
812 /* unmap the stencil buffer */
813 screen->transfer_unmap(screen, pt);
814 screen->tex_transfer_release(screen, &pt);
815 }
816
817
818 /**
819 * Called via ctx->Driver.DrawPixels()
820 */
821 static void
822 st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
823 GLenum format, GLenum type,
824 const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels)
825 {
826 struct st_fragment_program *stfp;
827 struct st_vertex_program *stvp;
828 struct st_context *st = ctx->st;
829 struct pipe_surface *ps;
830 GLuint bufferFormat;
831 const GLfloat *color;
832
833 if (format == GL_STENCIL_INDEX) {
834 draw_stencil_pixels(ctx, x, y, width, height, type, unpack, pixels);
835 return;
836 }
837
838 _mesa_set_vp_override( ctx, TRUE );
839 _mesa_update_state( ctx );
840
841 st_validate_state(st);
842
843 if (format == GL_DEPTH_COMPONENT) {
844 ps = st->state.framebuffer.zsbuf;
845 stfp = make_fragment_shader_z(ctx->st);
846 stvp = st_make_passthrough_vertex_shader(ctx->st, GL_TRUE);
847 color = ctx->Current.RasterColor;
848 }
849 else if (format == GL_STENCIL_INDEX) {
850 ps = st->state.framebuffer.zsbuf;
851 /* XXX special case - can't use texture map */
852 color = NULL;
853 }
854 else {
855 ps = st->state.framebuffer.cbufs[0];
856 stfp = combined_drawpix_fragment_program(ctx);
857 stvp = st_make_passthrough_vertex_shader(ctx->st, GL_FALSE);
858 color = NULL;
859 }
860
861 bufferFormat = ps->format;
862
863 if (1/*any_fragment_ops(st) ||
864 any_pixel_transfer_ops(st) ||
865 !compatible_formats(format, type, ps->format)*/) {
866 /* textured quad */
867 struct pipe_texture *pt
868 = make_texture(ctx->st, width, height, format, type, unpack, pixels);
869 if (pt) {
870 draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2],
871 width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
872 pt, stvp, stfp, color, GL_FALSE);
873 pipe_texture_reference(&pt, NULL);
874 }
875 }
876 else {
877 /* blit */
878 draw_blit(st, width, height, format, type, pixels);
879 }
880
881 _mesa_set_vp_override( ctx, FALSE );
882 }
883
884
885
886 static void
887 copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
888 GLsizei width, GLsizei height,
889 GLint dstx, GLint dsty)
890 {
891 struct st_renderbuffer *rbDraw = st_renderbuffer(ctx->DrawBuffer->_StencilBuffer);
892 struct pipe_screen *screen = ctx->st->pipe->screen;
893 struct pipe_transfer *ptDraw;
894 ubyte *drawMap;
895 ubyte *buffer;
896 int i;
897
898 buffer = _mesa_malloc(width * height * sizeof(ubyte));
899 if (!buffer) {
900 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels(stencil)");
901 return;
902 }
903
904 /* this will do stencil pixel transfer ops */
905 st_read_stencil_pixels(ctx, srcx, srcy, width, height, GL_UNSIGNED_BYTE,
906 &ctx->DefaultPacking, buffer);
907
908 ptDraw = screen->get_tex_transfer(screen, rbDraw->texture, 0, 0, 0,
909 PIPE_TRANSFER_WRITE, dstx, dsty,
910 width, height);
911
912 assert(ptDraw->block.width == 1);
913 assert(ptDraw->block.height == 1);
914
915 /* map the stencil buffer */
916 drawMap = screen->transfer_map(screen, ptDraw);
917
918 /* draw */
919 /* XXX PixelZoom not handled yet */
920 for (i = 0; i < height; i++) {
921 ubyte *dst;
922 const ubyte *src;
923 int y;
924
925 y = i;
926
927 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
928 y = height - y - 1;
929 }
930
931 dst = drawMap + y * ptDraw->stride;
932 src = buffer + i * width;
933
934 switch (ptDraw->format) {
935 case PIPE_FORMAT_S8Z24_UNORM:
936 {
937 uint *dst4 = (uint *) dst;
938 int j;
939 for (j = 0; j < width; j++) {
940 *dst4 = (*dst4 & 0xffffff) | (src[j] << 24);
941 dst4++;
942 }
943 }
944 break;
945 case PIPE_FORMAT_S8_UNORM:
946 memcpy(dst, src, width);
947 break;
948 default:
949 assert(0);
950 }
951 }
952
953 _mesa_free(buffer);
954
955 /* unmap the stencil buffer */
956 screen->transfer_unmap(screen, ptDraw);
957 screen->tex_transfer_release(screen, &ptDraw);
958 }
959
960
961 static void
962 st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
963 GLsizei width, GLsizei height,
964 GLint dstx, GLint dsty, GLenum type)
965 {
966 struct st_context *st = ctx->st;
967 struct pipe_context *pipe = st->pipe;
968 struct pipe_screen *screen = pipe->screen;
969 struct st_renderbuffer *rbRead;
970 struct st_vertex_program *stvp;
971 struct st_fragment_program *stfp;
972 struct pipe_texture *pt;
973 GLfloat *color;
974 enum pipe_format srcFormat, texFormat;
975
976 /* make sure rendering has completed */
977 pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
978
979 st_validate_state(st);
980
981 if (type == GL_STENCIL) {
982 /* can't use texturing to do stencil */
983 copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty);
984 return;
985 }
986
987 if (type == GL_COLOR) {
988 rbRead = st_get_color_read_renderbuffer(ctx);
989 color = NULL;
990 stfp = combined_drawpix_fragment_program(ctx);
991 stvp = st_make_passthrough_vertex_shader(ctx->st, GL_FALSE);
992 }
993 else {
994 assert(type == GL_DEPTH);
995 rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer);
996 color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
997 stfp = make_fragment_shader_z(ctx->st);
998 stvp = st_make_passthrough_vertex_shader(ctx->st, GL_TRUE);
999 }
1000
1001 srcFormat = rbRead->texture->format;
1002
1003 if (screen->is_format_supported(screen, srcFormat, PIPE_TEXTURE_2D,
1004 PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
1005 texFormat = srcFormat;
1006 }
1007 else {
1008 /* srcFormat can't be used as a texture format */
1009 if (type == GL_DEPTH) {
1010 texFormat = st_choose_format(pipe, GL_DEPTH_COMPONENT, PIPE_TEXTURE_2D,
1011 PIPE_TEXTURE_USAGE_DEPTH_STENCIL);
1012 assert(texFormat != PIPE_FORMAT_NONE); /* XXX no depth texture formats??? */
1013 }
1014 else {
1015 /* default color format */
1016 texFormat = st_choose_format(pipe, GL_RGBA, PIPE_TEXTURE_2D,
1017 PIPE_TEXTURE_USAGE_SAMPLER);
1018 assert(texFormat != PIPE_FORMAT_NONE);
1019 }
1020 }
1021
1022 pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, texFormat, 0,
1023 width, height, 1, 0,
1024 PIPE_TEXTURE_USAGE_SAMPLER);
1025 if (!pt)
1026 return;
1027
1028 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
1029 srcy = ctx->DrawBuffer->Height - srcy - height;
1030 }
1031
1032 if (srcFormat == texFormat) {
1033 /* copy source framebuffer surface into mipmap/texture */
1034 struct pipe_surface *psRead = screen->get_tex_surface(screen,
1035 rbRead->texture, 0, 0, 0,
1036 PIPE_BUFFER_USAGE_GPU_READ);
1037 struct pipe_surface *psTex = screen->get_tex_surface(screen, pt, 0, 0, 0,
1038 PIPE_BUFFER_USAGE_GPU_WRITE );
1039 pipe->surface_copy(pipe,
1040 FALSE,
1041 psTex, /* dest */
1042 0, 0, /* destx/y */
1043 psRead,
1044 srcx, srcy, width, height);
1045 pipe_surface_reference(&psRead, NULL);
1046 pipe_surface_reference(&psTex, NULL);
1047 }
1048 else {
1049 /* CPU-based fallback/conversion */
1050 struct pipe_transfer *ptRead =
1051 screen->get_tex_transfer(screen, rbRead->texture, 0, 0, 0,
1052 PIPE_TRANSFER_READ, srcx, srcy, width,
1053 height);
1054
1055 struct pipe_transfer *ptTex =
1056 screen->get_tex_transfer(screen, pt, 0, 0, 0, PIPE_TRANSFER_WRITE,
1057 0, 0, width, height);
1058
1059 if (type == GL_COLOR) {
1060 /* alternate path using get/put_tile() */
1061 GLfloat *buf = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
1062
1063 pipe_get_tile_rgba(ptRead, 0, 0, width, height, buf);
1064 pipe_put_tile_rgba(ptTex, 0, 0, width, height, buf);
1065
1066 _mesa_free(buf);
1067 }
1068 else {
1069 /* GL_DEPTH */
1070 GLuint *buf = (GLuint *) _mesa_malloc(width * height * sizeof(GLuint));
1071 pipe_get_tile_z(ptRead, 0, 0, width, height, buf);
1072 pipe_put_tile_z(ptTex, 0, 0, width, height, buf);
1073 _mesa_free(buf);
1074 }
1075
1076 screen->tex_transfer_release(screen, &ptRead);
1077 screen->tex_transfer_release(screen, &ptTex);
1078 }
1079
1080 /* draw textured quad */
1081 draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2],
1082 width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
1083 pt, stvp, stfp, color, GL_TRUE);
1084
1085 pipe_texture_reference(&pt, NULL);
1086 }
1087
1088
1089
1090 void st_init_drawpixels_functions(struct dd_function_table *functions)
1091 {
1092 functions->DrawPixels = st_DrawPixels;
1093 functions->CopyPixels = st_CopyPixels;
1094 }
1095
1096
1097 void
1098 st_destroy_drawpix(struct st_context *st)
1099 {
1100 st_reference_fragprog(st, &st->drawpix.z_shader, NULL);
1101 st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL);
1102 st_reference_vertprog(st, &st->drawpix.vert_shaders[0], NULL);
1103 st_reference_vertprog(st, &st->drawpix.vert_shaders[1], NULL);
1104 }
1105
1106