2db12c653b6adc4f3ae87fdbad8fe1d74c33c2a9
[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/macros.h"
36 #include "main/texformat.h"
37 #include "shader/program.h"
38 #include "shader/prog_parameter.h"
39 #include "shader/prog_print.h"
40
41 #include "st_context.h"
42 #include "st_atom.h"
43 #include "st_atom_constbuf.h"
44 #include "st_cache.h"
45 #include "st_draw.h"
46 #include "st_program.h"
47 #include "st_cb_drawpixels.h"
48 #include "st_cb_readpixels.h"
49 #include "st_cb_fbo.h"
50 #include "st_cb_texture.h"
51 #include "st_draw.h"
52 #include "st_format.h"
53 #include "st_mesa_to_tgsi.h"
54 #include "st_texture.h"
55 #include "pipe/p_context.h"
56 #include "pipe/p_defines.h"
57 #include "pipe/p_inlines.h"
58 #include "pipe/p_winsys.h"
59 #include "shader/prog_instruction.h"
60
61
62 /**
63 * Check if the given program is:
64 * 0: MOVE result.color, fragment.color;
65 * 1: END;
66 */
67 static GLboolean
68 is_passthrough_program(const struct gl_fragment_program *prog)
69 {
70 if (prog->Base.NumInstructions == 2) {
71 const struct prog_instruction *inst = prog->Base.Instructions;
72 if (inst[0].Opcode == OPCODE_MOV &&
73 inst[1].Opcode == OPCODE_END &&
74 inst[0].DstReg.File == PROGRAM_OUTPUT &&
75 inst[0].DstReg.Index == FRAG_RESULT_COLR &&
76 inst[0].DstReg.WriteMask == WRITEMASK_XYZW &&
77 inst[0].SrcReg[0].File == PROGRAM_INPUT &&
78 inst[0].SrcReg[0].Index == FRAG_ATTRIB_COL0 &&
79 inst[0].SrcReg[0].Swizzle == SWIZZLE_XYZW) {
80 return GL_TRUE;
81 }
82 }
83 return GL_FALSE;
84 }
85
86
87 /**
88 * Make fragment program for glBitmap:
89 * Sample the texture and kill the fragment if the bit is 0.
90 * This program will be combined with the user's fragment program.
91 */
92 static struct st_fragment_program *
93 make_bitmap_fragment_program(GLcontext *ctx)
94 {
95 struct st_fragment_program *stfp;
96 struct gl_program *p;
97 GLuint ic = 0;
98
99 p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
100 if (!p)
101 return NULL;
102
103 p->NumInstructions = 5;
104
105 p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
106 if (!p->Instructions) {
107 ctx->Driver.DeleteProgram(ctx, p);
108 return NULL;
109 }
110 _mesa_init_instructions(p->Instructions, p->NumInstructions);
111
112 /* TEX tmp0, fragment.texcoord[0], texture[0], 2D; */
113 p->Instructions[ic].Opcode = OPCODE_TEX;
114 p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY;
115 p->Instructions[ic].DstReg.Index = 0;
116 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
117 p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
118 p->Instructions[ic].TexSrcUnit = 0;
119 p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
120 ic++;
121
122 /* SWZ tmp0.x, tmp0.x, 1111; # tmp0.x = 1.0 */
123 p->Instructions[ic].Opcode = OPCODE_SWZ;
124 p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY;
125 p->Instructions[ic].DstReg.Index = 0;
126 p->Instructions[ic].DstReg.WriteMask = WRITEMASK_X;
127 p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
128 p->Instructions[ic].SrcReg[0].Index = 0;
129 p->Instructions[ic].SrcReg[0].Swizzle
130 = MAKE_SWIZZLE4(SWIZZLE_ONE, SWIZZLE_ONE, SWIZZLE_ONE, SWIZZLE_ONE );
131 ic++;
132
133 /* SUB tmp0, tmp0.wwww, tmp0.xxxx; # tmp0.w -= 1 */
134 p->Instructions[ic].Opcode = OPCODE_SUB;
135 p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY;
136 p->Instructions[ic].DstReg.Index = 0;
137 p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
138 p->Instructions[ic].SrcReg[0].Index = 0;
139 p->Instructions[ic].SrcReg[0].Swizzle = SWIZZLE_WWWW;
140 p->Instructions[ic].SrcReg[1].File = PROGRAM_TEMPORARY;
141 p->Instructions[ic].SrcReg[1].Index = 0;
142 p->Instructions[ic].SrcReg[1].Swizzle = SWIZZLE_XXXX; /* 1.0 */
143 ic++;
144
145 /* KIL if tmp0 < 0 */
146 p->Instructions[ic].Opcode = OPCODE_KIL;
147 p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
148 p->Instructions[ic].SrcReg[0].Index = 0;
149 ic++;
150
151 /* END; */
152 p->Instructions[ic++].Opcode = OPCODE_END;
153
154 assert(ic == p->NumInstructions);
155
156 p->InputsRead = FRAG_BIT_TEX0;
157 p->OutputsWritten = 0x0;
158
159 stfp = (struct st_fragment_program *) p;
160 st_translate_fragment_program(ctx->st, stfp, NULL,
161 stfp->tokens, ST_MAX_SHADER_TOKENS);
162
163 return stfp;
164 }
165
166
167 /**
168 * Combine basic bitmap fragment program with the user-defined program.
169 */
170 static struct st_fragment_program *
171 combined_bitmap_fragment_program(GLcontext *ctx)
172 {
173 struct st_context *st = ctx->st;
174 struct st_fragment_program *stfp;
175
176 if (!st->bitmap.program) {
177 /* create the basic bitmap fragment program */
178 st->bitmap.program = make_bitmap_fragment_program(ctx);
179 }
180
181 if (st->bitmap.user_prog_sn == st->fp->serialNo) {
182 /* re-use */
183 stfp = st->bitmap.combined_prog;
184 }
185 else {
186 /* Concatenate the bitmap program with the current user-defined program.
187 */
188 stfp = (struct st_fragment_program *)
189 _mesa_combine_programs(ctx,
190 &st->bitmap.program->Base.Base,
191 &st->fp->Base.Base);
192
193 #if 0
194 {
195 struct gl_program *p = &stfp->Base.Base;
196 printf("Combined bitmap program:\n");
197 _mesa_print_program(p);
198 printf("InputsRead: 0x%x\n", p->InputsRead);
199 printf("OutputsWritten: 0x%x\n", p->OutputsWritten);
200 _mesa_print_parameter_list(p->Parameters);
201 }
202 #endif
203
204 /* translate to TGSI tokens */
205 st_translate_fragment_program(st, stfp, NULL,
206 stfp->tokens, ST_MAX_SHADER_TOKENS);
207
208 /* save new program, update serial numbers */
209 st->bitmap.user_prog_sn = st->fp->serialNo;
210 st->bitmap.combined_prog = stfp;
211 }
212
213 /* Ideally we'd have updated the pipe constants during the normal
214 * st/atom mechanism. But we can't since this is specific to glBitmap.
215 */
216 st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT);
217
218 return stfp;
219 }
220
221
222
223 /**
224 * Make fragment shader for glDraw/CopyPixels. This shader is made
225 * by combining the pixel transfer shader with the user-defined shader.
226 */
227 static struct st_fragment_program *
228 combined_drawpix_fragment_program(GLcontext *ctx)
229 {
230 struct st_context *st = ctx->st;
231 struct st_fragment_program *stfp;
232
233 if (st->pixel_xfer.program->serialNo == st->pixel_xfer.xfer_prog_sn
234 && st->fp->serialNo == st->pixel_xfer.user_prog_sn) {
235 /* the pixel tranfer program has not changed and the user-defined
236 * program has not changed, so re-use the combined program.
237 */
238 stfp = st->pixel_xfer.combined_prog;
239 }
240 else {
241 /* Concatenate the pixel transfer program with the current user-
242 * defined program.
243 */
244 if (is_passthrough_program(&st->fp->Base)) {
245 stfp = (struct st_fragment_program *)
246 _mesa_clone_program(ctx, &st->pixel_xfer.program->Base.Base);
247 }
248 else {
249 stfp = (struct st_fragment_program *)
250 _mesa_combine_programs(ctx,
251 &st->pixel_xfer.program->Base.Base,
252 &st->fp->Base.Base);
253 }
254
255 #if 0
256 {
257 struct gl_program *p = &stfp->Base.Base;
258 printf("Combined DrawPixels program:\n");
259 _mesa_print_program(p);
260 printf("InputsRead: 0x%x\n", p->InputsRead);
261 printf("OutputsWritten: 0x%x\n", p->OutputsWritten);
262 _mesa_print_parameter_list(p->Parameters);
263 }
264 #endif
265
266 /* translate to TGSI tokens */
267 st_translate_fragment_program(st, stfp, NULL,
268 stfp->tokens, ST_MAX_SHADER_TOKENS);
269
270 /* save new program, update serial numbers */
271 st->pixel_xfer.xfer_prog_sn = st->pixel_xfer.program->serialNo;
272 st->pixel_xfer.user_prog_sn = st->fp->serialNo;
273 st->pixel_xfer.combined_prog_sn = stfp->serialNo;
274 st->pixel_xfer.combined_prog = stfp;
275 }
276
277 /* Ideally we'd have updated the pipe constants during the normal
278 * st/atom mechanism. But we can't since this is specific to glDrawPixels.
279 */
280 st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT);
281
282 return stfp;
283 }
284
285
286 /**
287 * Create fragment shader that does a TEX() instruction to get a Z
288 * value, then writes to FRAG_RESULT_DEPR.
289 * Pass fragment color through as-is.
290 */
291 static struct st_fragment_program *
292 make_fragment_shader_z(struct st_context *st)
293 {
294 GLcontext *ctx = st->ctx;
295 /* only make programs once and re-use */
296 static struct st_fragment_program *stfp = NULL;
297 struct gl_program *p;
298 GLuint ic = 0;
299
300 if (stfp)
301 return stfp;
302
303 p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
304 if (!p)
305 return NULL;
306
307 p->NumInstructions = 3;
308
309 p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
310 if (!p->Instructions) {
311 ctx->Driver.DeleteProgram(ctx, p);
312 return NULL;
313 }
314 _mesa_init_instructions(p->Instructions, p->NumInstructions);
315
316 /* TEX result.depth, fragment.texcoord[0], texture[0], 2D; */
317 p->Instructions[ic].Opcode = OPCODE_TEX;
318 p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
319 p->Instructions[ic].DstReg.Index = FRAG_RESULT_DEPR;
320 p->Instructions[ic].DstReg.WriteMask = WRITEMASK_Z;
321 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
322 p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
323 p->Instructions[ic].TexSrcUnit = 0;
324 p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
325 ic++;
326
327 /* MOV result.color, fragment.color */
328 p->Instructions[ic].Opcode = OPCODE_MOV;
329 p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
330 p->Instructions[ic].DstReg.Index = FRAG_RESULT_COLR;
331 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
332 p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_COL0;
333 ic++;
334
335 /* END; */
336 p->Instructions[ic++].Opcode = OPCODE_END;
337
338 assert(ic == p->NumInstructions);
339
340 p->InputsRead = FRAG_BIT_TEX0 | FRAG_BIT_COL0;
341 p->OutputsWritten = (1 << FRAG_RESULT_COLR) | (1 << FRAG_RESULT_DEPR);
342
343 stfp = (struct st_fragment_program *) p;
344 st_translate_fragment_program(st, stfp, NULL,
345 stfp->tokens, ST_MAX_SHADER_TOKENS);
346
347 return stfp;
348 }
349
350
351
352 /**
353 * Create a simple vertex shader that just passes through the
354 * vertex position and texcoord (and optionally, color).
355 */
356 static struct st_vertex_program *
357 make_vertex_shader(struct st_context *st, GLboolean passColor)
358 {
359 /* only make programs once and re-use */
360 static struct st_vertex_program *progs[2] = { NULL, NULL };
361 GLcontext *ctx = st->ctx;
362 struct st_vertex_program *stvp;
363 struct gl_program *p;
364 GLuint ic = 0;
365
366 if (progs[passColor])
367 return progs[passColor];
368
369 p = ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
370 if (!p)
371 return NULL;
372
373 if (passColor)
374 p->NumInstructions = 4;
375 else
376 p->NumInstructions = 3;
377
378 p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
379 if (!p->Instructions) {
380 ctx->Driver.DeleteProgram(ctx, p);
381 return NULL;
382 }
383 _mesa_init_instructions(p->Instructions, p->NumInstructions);
384 /* MOV result.pos, vertex.pos; */
385 p->Instructions[0].Opcode = OPCODE_MOV;
386 p->Instructions[0].DstReg.File = PROGRAM_OUTPUT;
387 p->Instructions[0].DstReg.Index = VERT_RESULT_HPOS;
388 p->Instructions[0].SrcReg[0].File = PROGRAM_INPUT;
389 p->Instructions[0].SrcReg[0].Index = VERT_ATTRIB_POS;
390 /* MOV result.texcoord0, vertex.texcoord0; */
391 p->Instructions[1].Opcode = OPCODE_MOV;
392 p->Instructions[1].DstReg.File = PROGRAM_OUTPUT;
393 p->Instructions[1].DstReg.Index = VERT_RESULT_TEX0;
394 p->Instructions[1].SrcReg[0].File = PROGRAM_INPUT;
395 p->Instructions[1].SrcReg[0].Index = VERT_ATTRIB_TEX0;
396 ic = 2;
397 if (passColor) {
398 /* MOV result.color0, vertex.color0; */
399 p->Instructions[ic].Opcode = OPCODE_MOV;
400 p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
401 p->Instructions[ic].DstReg.Index = VERT_RESULT_COL0;
402 p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
403 p->Instructions[ic].SrcReg[0].Index = VERT_ATTRIB_COLOR0;
404 ic++;
405 }
406
407 /* END; */
408 p->Instructions[ic].Opcode = OPCODE_END;
409 ic++;
410
411 assert(ic == p->NumInstructions);
412
413 p->InputsRead = VERT_BIT_POS | VERT_BIT_TEX0;
414 p->OutputsWritten = ((1 << VERT_RESULT_TEX0) |
415 (1 << VERT_RESULT_HPOS));
416 if (passColor) {
417 p->InputsRead |= VERT_BIT_COLOR0;
418 p->OutputsWritten |= (1 << VERT_RESULT_COL0);
419 }
420
421 stvp = (struct st_vertex_program *) p;
422 st_translate_vertex_program(st, stvp, NULL,
423 stvp->tokens, ST_MAX_SHADER_TOKENS);
424
425 progs[passColor] = stvp;
426
427 return stvp;
428 }
429
430
431 static GLenum
432 _mesa_base_format(GLenum format)
433 {
434 switch (format) {
435 case GL_DEPTH_COMPONENT:
436 return GL_DEPTH_COMPONENT;
437 case GL_STENCIL_INDEX:
438 return GL_STENCIL_INDEX;
439 default:
440 return GL_RGBA;
441 }
442 }
443
444
445 /**
446 * Make texture containing an image for glDrawPixels image.
447 * If 'pixels' is NULL, leave the texture image data undefined.
448 */
449 static struct pipe_texture *
450 make_texture(struct st_context *st,
451 GLsizei width, GLsizei height, GLenum format, GLenum type,
452 const struct gl_pixelstore_attrib *unpack,
453 const GLvoid *pixels)
454 {
455 GLcontext *ctx = st->ctx;
456 struct pipe_context *pipe = st->pipe;
457 const struct gl_texture_format *mformat;
458 struct pipe_texture *pt;
459 enum pipe_format pipeFormat;
460 GLuint cpp;
461 GLenum baseFormat;
462
463 baseFormat = _mesa_base_format(format);
464
465 mformat = st_ChooseTextureFormat(ctx, baseFormat, format, type);
466 assert(mformat);
467
468 pipeFormat = st_mesa_format_to_pipe_format(mformat->MesaFormat);
469 assert(pipeFormat);
470 cpp = st_sizeof_format(pipeFormat);
471
472 pt = st_texture_create(st, PIPE_TEXTURE_2D, pipeFormat, 0, 0, width, height,
473 1, 0);
474 if (!pt)
475 return NULL;
476
477 if (unpack->BufferObj && unpack->BufferObj->Name) {
478 /*
479 pt->region = buffer_object_region(unpack->BufferObj);
480 */
481 printf("st_DrawPixels (sourcing from PBO not implemented yet)\n");
482 }
483
484 {
485 struct pipe_surface *surface;
486 static const GLuint dstImageOffsets = 0;
487 GLboolean success;
488 GLubyte *dest;
489 const GLbitfield imageTransferStateSave = ctx->_ImageTransferState;
490
491 /* we'll do pixel transfer in a fragment shader */
492 ctx->_ImageTransferState = 0x0;
493
494 surface = pipe->get_tex_surface(pipe, pt, 0, 0, 0);
495
496 /* map texture surface */
497 dest = pipe_surface_map(surface);
498
499 /* Put image into texture surface.
500 * Note that the image is actually going to be upside down in
501 * the texture. We deal with that with texcoords.
502 */
503 success = mformat->StoreImage(ctx, 2, /* dims */
504 baseFormat, /* baseInternalFormat */
505 mformat, /* gl_texture_format */
506 dest, /* dest */
507 0, 0, 0, /* dstX/Y/Zoffset */
508 surface->pitch * cpp, /* dstRowStride, bytes */
509 &dstImageOffsets, /* dstImageOffsets */
510 width, height, 1, /* size */
511 format, type, /* src format/type */
512 pixels, /* data source */
513 unpack);
514
515 /* unmap */
516 pipe_surface_unmap(surface);
517 pipe_surface_reference(&surface, NULL);
518 assert(success);
519
520 /* restore */
521 ctx->_ImageTransferState = imageTransferStateSave;
522 }
523
524 return pt;
525 }
526
527
528 /**
529 * Draw textured quad.
530 * Coords are window coords with y=0=bottom.
531 */
532 static void
533 draw_quad(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z,
534 GLfloat x1, GLfloat y1, GLboolean invertTex)
535 {
536 GLfloat verts[4][2][4]; /* four verts, two attribs, XYZW */
537 GLuint i;
538 GLfloat tTop = invertTex, tBot = 1.0 - tTop;
539
540 /* upper-left */
541 verts[0][0][0] = x0; /* attr[0].x */
542 verts[0][0][1] = y0; /* attr[0].x */
543 verts[0][1][0] = 0.0; /* attr[1].s */
544 verts[0][1][1] = tTop; /* attr[1].t */
545
546 /* upper-right */
547 verts[1][0][0] = x1;
548 verts[1][0][1] = y0;
549 verts[1][1][0] = 1.0;
550 verts[1][1][1] = tTop;
551
552 /* lower-right */
553 verts[2][0][0] = x1;
554 verts[2][0][1] = y1;
555 verts[2][1][0] = 1.0;
556 verts[2][1][1] = tBot;
557
558 /* lower-left */
559 verts[3][0][0] = x0;
560 verts[3][0][1] = y1;
561 verts[3][1][0] = 0.0;
562 verts[3][1][1] = tBot;
563
564 /* same for all verts: */
565 for (i = 0; i < 4; i++) {
566 verts[i][0][2] = z; /*Z*/
567 verts[i][0][3] = 1.0; /*W*/
568 verts[i][1][2] = 0.0; /*R*/
569 verts[i][1][3] = 1.0; /*Q*/
570 }
571
572 st_draw_vertices(ctx, PIPE_PRIM_QUADS, 4, (float *) verts, 2);
573 }
574
575
576 static void
577 draw_quad_colored(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z,
578 GLfloat x1, GLfloat y1, const GLfloat *color,
579 GLboolean invertTex)
580 {
581 GLfloat verts[4][3][4]; /* four verts, three attribs, XYZW */
582 GLuint i;
583 GLfloat tTop = invertTex, tBot = 1.0 - tTop;
584
585 /* upper-left */
586 verts[0][0][0] = x0; /* attr[0].x */
587 verts[0][0][1] = y0; /* attr[0].y */
588 verts[0][2][0] = 0.0; /* attr[2].s */
589 verts[0][2][1] = tTop; /* attr[2].t */
590
591 /* upper-right */
592 verts[1][0][0] = x1;
593 verts[1][0][1] = y0;
594 verts[1][2][0] = 1.0;
595 verts[1][2][1] = tTop;
596
597 /* lower-right */
598 verts[2][0][0] = x1;
599 verts[2][0][1] = y1;
600 verts[2][2][0] = 1.0;
601 verts[2][2][1] = tBot;
602
603 /* lower-left */
604 verts[3][0][0] = x0;
605 verts[3][0][1] = y1;
606 verts[3][2][0] = 0.0;
607 verts[3][2][1] = tBot;
608
609 /* same for all verts: */
610 for (i = 0; i < 4; i++) {
611 verts[i][0][2] = z; /*Z*/
612 verts[i][0][3] = 1.0; /*W*/
613 verts[i][1][0] = color[0];
614 verts[i][1][1] = color[1];
615 verts[i][1][2] = color[2];
616 verts[i][1][3] = color[3];
617 verts[i][2][2] = 0.0; /*R*/
618 verts[i][2][3] = 1.0; /*Q*/
619 }
620
621 st_draw_vertices(ctx, PIPE_PRIM_QUADS, 4, (float *) verts, 3);
622 }
623
624
625
626 static void
627 draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
628 GLsizei width, GLsizei height,
629 GLfloat zoomX, GLfloat zoomY,
630 struct pipe_texture *pt,
631 struct st_vertex_program *stvp,
632 struct st_fragment_program *stfp,
633 const GLfloat *color,
634 GLboolean invertTex)
635 {
636 const GLuint unit = 0;
637 struct pipe_context *pipe = ctx->st->pipe;
638 GLfloat x0, y0, x1, y1;
639 GLuint maxSize;
640
641 /* limit checks */
642 /* XXX if DrawPixels image is larger than max texture size, break
643 * it up into chunks.
644 */
645 maxSize = 1 << (pipe->get_param(pipe, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
646 assert(width <= maxSize);
647 assert(height <= maxSize);
648
649 /* setup state: just scissor */
650 {
651 struct pipe_rasterizer_state setup;
652 const struct cso_rasterizer *cso;
653 memset(&setup, 0, sizeof(setup));
654 if (ctx->Scissor.Enabled)
655 setup.scissor = 1;
656 cso = st_cached_rasterizer_state(ctx->st, &setup);
657 pipe->bind_rasterizer_state(pipe, cso->data);
658 }
659
660 /* fragment shader state: TEX lookup program */
661 pipe->bind_fs_state(pipe, stfp->fs->data);
662
663 /* vertex shader state: position + texcoord pass-through */
664 pipe->bind_vs_state(pipe, stvp->vs->data);
665
666 /* texture sampling state: */
667 {
668 struct pipe_sampler_state sampler;
669 const struct cso_sampler *cso;
670 memset(&sampler, 0, sizeof(sampler));
671 sampler.wrap_s = PIPE_TEX_WRAP_REPEAT;
672 sampler.wrap_t = PIPE_TEX_WRAP_REPEAT;
673 sampler.wrap_r = PIPE_TEX_WRAP_REPEAT;
674 sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
675 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
676 sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
677 sampler.normalized_coords = 1;
678 cso = st_cached_sampler_state(ctx->st, &sampler);
679 pipe->bind_sampler_state(pipe, unit, cso->data);
680 }
681
682 /* viewport state: viewport matching window dims */
683 {
684 const float width = ctx->DrawBuffer->Width;
685 const float height = ctx->DrawBuffer->Height;
686 struct pipe_viewport_state vp;
687 vp.scale[0] = 0.5 * width;
688 vp.scale[1] = -0.5 * height;
689 vp.scale[2] = 1.0;
690 vp.scale[3] = 1.0;
691 vp.translate[0] = 0.5 * width;
692 vp.translate[1] = 0.5 * height;
693 vp.translate[2] = 0.0;
694 vp.translate[3] = 0.0;
695 pipe->set_viewport_state(pipe, &vp);
696 }
697
698 /* texture state: */
699 {
700 pipe->set_sampler_texture(pipe, unit, pt);
701 }
702
703 /* Compute window coords (y=0=bottom) with pixel zoom.
704 * Recall that these coords are transformed by the current
705 * vertex shader and viewport transformation.
706 */
707 x0 = x;
708 x1 = x + width * ctx->Pixel.ZoomX;
709 y0 = y;
710 y1 = y + height * ctx->Pixel.ZoomY;
711
712 /* draw textured quad */
713 if (color)
714 draw_quad_colored(ctx, x0, y0, z, x1, y1, color, invertTex);
715 else
716 draw_quad(ctx, x0, y0, z, x1, y1, invertTex);
717
718 /* restore GL state */
719 pipe->bind_rasterizer_state(pipe, ctx->st->state.rasterizer->data);
720 pipe->bind_fs_state(pipe, ctx->st->state.fs->data);
721 pipe->bind_vs_state(pipe, ctx->st->state.vs->data);
722 pipe->set_sampler_texture(pipe, unit, ctx->st->state.sampler_texture[unit]);
723 pipe->bind_sampler_state(pipe, unit, ctx->st->state.sampler[unit]->data);
724 pipe->set_viewport_state(pipe, &ctx->st->state.viewport);
725 }
726
727
728 /**
729 * Check if a GL format/type combination is a match to the given pipe format.
730 * XXX probably move this to a re-usable place.
731 */
732 static GLboolean
733 compatible_formats(GLenum format, GLenum type, enum pipe_format pipeFormat)
734 {
735 static const GLuint one = 1;
736 GLubyte littleEndian = *((GLubyte *) &one);
737
738 if (pipeFormat == PIPE_FORMAT_R8G8B8A8_UNORM &&
739 format == GL_RGBA &&
740 type == GL_UNSIGNED_BYTE &&
741 !littleEndian) {
742 return GL_TRUE;
743 }
744 else if (pipeFormat == PIPE_FORMAT_R8G8B8A8_UNORM &&
745 format == GL_ABGR_EXT &&
746 type == GL_UNSIGNED_BYTE &&
747 littleEndian) {
748 return GL_TRUE;
749 }
750 else if (pipeFormat == PIPE_FORMAT_A8R8G8B8_UNORM &&
751 format == GL_BGRA &&
752 type == GL_UNSIGNED_BYTE &&
753 littleEndian) {
754 return GL_TRUE;
755 }
756 else if (pipeFormat == PIPE_FORMAT_R5G6B5_UNORM &&
757 format == GL_RGB &&
758 type == GL_UNSIGNED_SHORT_5_6_5) {
759 /* endian don't care */
760 return GL_TRUE;
761 }
762 else if (pipeFormat == PIPE_FORMAT_R5G6B5_UNORM &&
763 format == GL_BGR &&
764 type == GL_UNSIGNED_SHORT_5_6_5_REV) {
765 /* endian don't care */
766 return GL_TRUE;
767 }
768 else if (pipeFormat == PIPE_FORMAT_S8_UNORM &&
769 format == GL_STENCIL_INDEX &&
770 type == GL_UNSIGNED_BYTE) {
771 return GL_TRUE;
772 }
773 else if (pipeFormat == PIPE_FORMAT_Z32_UNORM &&
774 format == GL_DEPTH_COMPONENT &&
775 type == GL_UNSIGNED_INT) {
776 return GL_TRUE;
777 }
778 /* XXX add more cases */
779 else {
780 return GL_FALSE;
781 }
782 }
783
784
785 /**
786 * Check if any per-fragment ops are enabled.
787 * XXX probably move this to a re-usable place.
788 */
789 static GLboolean
790 any_fragment_ops(const struct st_context *st)
791 {
792 if (st->state.depth_stencil->state.alpha.enabled ||
793 st->state.blend->state.blend_enable ||
794 st->state.blend->state.logicop_enable ||
795 st->state.depth_stencil->state.depth.enabled)
796 /* XXX more checks */
797 return GL_TRUE;
798 else
799 return GL_FALSE;
800 }
801
802
803 /**
804 * Check if any pixel transfer ops are enabled.
805 * XXX probably move this to a re-usable place.
806 */
807 static GLboolean
808 any_pixel_transfer_ops(const struct st_context *st)
809 {
810 if (st->ctx->Pixel.RedScale != 1.0 ||
811 st->ctx->Pixel.RedBias != 0.0 ||
812 st->ctx->Pixel.GreenScale != 1.0 ||
813 st->ctx->Pixel.GreenBias != 0.0 ||
814 st->ctx->Pixel.BlueScale != 1.0 ||
815 st->ctx->Pixel.BlueBias != 0.0 ||
816 st->ctx->Pixel.AlphaScale != 1.0 ||
817 st->ctx->Pixel.AlphaBias != 0.0 ||
818 st->ctx->Pixel.MapColorFlag)
819 /* XXX more checks */
820 return GL_TRUE;
821 else
822 return GL_FALSE;
823 }
824
825
826 /**
827 * Draw image with a blit, or other non-textured quad method.
828 */
829 static void
830 draw_blit(struct st_context *st,
831 GLsizei width, GLsizei height,
832 GLenum format, GLenum type, const GLvoid *pixels)
833 {
834
835
836 }
837
838
839 static void
840 draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
841 GLsizei width, GLsizei height, GLenum type,
842 const struct gl_pixelstore_attrib *unpack,
843 const GLvoid *pixels)
844 {
845 struct st_context *st = ctx->st;
846 struct pipe_context *pipe = st->pipe;
847 struct pipe_surface *ps = st->state.framebuffer.sbuf;
848 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
849 GLint skipPixels;
850 ubyte *stmap;
851
852 pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE);
853
854 /* map the stencil buffer */
855 stmap = pipe_surface_map(ps);
856
857 /* if width > MAX_WIDTH, have to process image in chunks */
858 skipPixels = 0;
859 while (skipPixels < width) {
860 const GLint spanX = x + skipPixels;
861 const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
862 GLint row;
863 for (row = 0; row < height; row++) {
864 GLint spanY = y + row;
865 GLubyte values[MAX_WIDTH];
866 GLenum destType = GL_UNSIGNED_BYTE;
867 const GLvoid *source = _mesa_image_address2d(unpack, pixels,
868 width, height,
869 GL_COLOR_INDEX, type,
870 row, skipPixels);
871 _mesa_unpack_stencil_span(ctx, spanWidth, destType, values,
872 type, source, unpack,
873 ctx->_ImageTransferState);
874 if (zoom) {
875 /*
876 _swrast_write_zoomed_stencil_span(ctx, x, y, spanWidth,
877 spanX, spanY, values);
878 */
879 }
880 else {
881 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
882 spanY = ctx->DrawBuffer->Height - spanY - 1;
883 }
884
885 switch (ps->format) {
886 case PIPE_FORMAT_U_S8:
887 {
888 ubyte *dest = stmap + spanY * ps->pitch + spanX;
889 memcpy(dest, values, spanWidth);
890 }
891 break;
892 case PIPE_FORMAT_S8Z24_UNORM:
893 {
894 uint *dest = (uint *) stmap + spanY * ps->pitch + spanX;
895 GLint k;
896 for (k = 0; k < spanWidth; k++) {
897 uint p = dest[k];
898 p = (p & 0xffffff) | (values[k] << 24);
899 dest[k] = p;
900 }
901 }
902 break;
903 default:
904 assert(0);
905 }
906 }
907 }
908 skipPixels += spanWidth;
909 }
910
911 /* unmap the stencil buffer */
912 pipe_surface_unmap(ps);
913 }
914
915
916 /**
917 * Called via ctx->Driver.DrawPixels()
918 */
919 static void
920 st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
921 GLenum format, GLenum type,
922 const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels)
923 {
924 struct st_fragment_program *stfp;
925 struct st_vertex_program *stvp;
926 struct st_context *st = ctx->st;
927 struct pipe_surface *ps;
928 GLuint bufferFormat;
929 const GLfloat *color;
930
931 if (format == GL_STENCIL_INDEX) {
932 draw_stencil_pixels(ctx, x, y, width, height, type, unpack, pixels);
933 return;
934 }
935
936 st_validate_state(st);
937
938 if (format == GL_DEPTH_COMPONENT) {
939 ps = st->state.framebuffer.zbuf;
940 stfp = make_fragment_shader_z(ctx->st);
941 stvp = make_vertex_shader(ctx->st, GL_TRUE);
942 color = ctx->Current.RasterColor;
943 }
944 else if (format == GL_STENCIL_INDEX) {
945 ps = st->state.framebuffer.sbuf;
946 /* XXX special case - can't use texture map */
947 color = NULL;
948 }
949 else {
950 ps = st->state.framebuffer.cbufs[0];
951 stfp = combined_drawpix_fragment_program(ctx);
952 stvp = make_vertex_shader(ctx->st, GL_FALSE);
953 color = NULL;
954 }
955
956 bufferFormat = ps->format;
957
958 if (any_fragment_ops(st) ||
959 any_pixel_transfer_ops(st) ||
960 !compatible_formats(format, type, ps->format)) {
961 /* textured quad */
962 struct pipe_texture *pt
963 = make_texture(ctx->st, width, height, format, type, unpack, pixels);
964 if (pt) {
965 draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2],
966 width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
967 pt, stvp, stfp, color, GL_FALSE);
968 st->pipe->texture_release(st->pipe, &pt);
969 }
970 }
971 else {
972 /* blit */
973 draw_blit(st, width, height, format, type, pixels);
974 }
975 }
976
977
978
979 /**
980 * Create a texture which represents a bitmap image.
981 */
982 static struct pipe_texture *
983 make_bitmap_texture(GLcontext *ctx, GLsizei width, GLsizei height,
984 const struct gl_pixelstore_attrib *unpack,
985 const GLubyte *bitmap)
986 {
987 struct pipe_context *pipe = ctx->st->pipe;
988 struct pipe_surface *surface;
989 uint format = 0, cpp, comp;
990 ubyte *dest;
991 struct pipe_texture *pt;
992 int row, col;
993
994 /* find a texture format we know */
995 if (pipe->is_format_supported( pipe, PIPE_FORMAT_U_I8, PIPE_TEXTURE )) {
996 format = PIPE_FORMAT_U_I8;
997 cpp = 1;
998 comp = 0;
999 }
1000 else if (pipe->is_format_supported( pipe, PIPE_FORMAT_A8R8G8B8_UNORM, PIPE_TEXTURE )) {
1001 format = PIPE_FORMAT_A8R8G8B8_UNORM;
1002 cpp = 4;
1003 comp = 3; /* alpha channel */ /*XXX little-endian dependency */
1004 }
1005 else {
1006 /* XXX support more formats */
1007 assert( 0 );
1008 }
1009
1010 /**
1011 * Create a texture.
1012 */
1013 pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, format, 0, 0, width, height,
1014 1, 0);
1015 if (!pt)
1016 return NULL;
1017
1018 if (unpack->BufferObj && unpack->BufferObj->Name) {
1019 /*
1020 pt->region = buffer_object_region(unpack->BufferObj);
1021 */
1022 printf("st_Bitmap (sourcing from PBO not implemented yet)\n");
1023 }
1024
1025 surface = pipe->get_tex_surface(pipe, pt, 0, 0, 0);
1026
1027 /* map texture surface */
1028 dest = pipe_surface_map(surface);
1029
1030 /* Put image into texture surface.
1031 * Note that the image is actually going to be upside down in
1032 * the texture. We deal with that with texcoords.
1033 */
1034
1035 for (row = 0; row < height; row++) {
1036 const GLubyte *src = (const GLubyte *) _mesa_image_address2d(unpack,
1037 bitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, row, 0);
1038 ubyte *destRow = dest + row * surface->pitch * cpp;
1039
1040 if (unpack->LsbFirst) {
1041 /* Lsb first */
1042 GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
1043 for (col = 0; col < width; col++) {
1044
1045 /* set texel to 255 if bit is set */
1046 destRow[comp] = (*src & mask) ? 255 : 0;
1047 destRow += cpp;
1048
1049 if (mask == 128U) {
1050 src++;
1051 mask = 1U;
1052 }
1053 else {
1054 mask = mask << 1;
1055 }
1056 }
1057
1058 /* get ready for next row */
1059 if (mask != 1)
1060 src++;
1061 }
1062 else {
1063 /* Msb first */
1064 GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
1065 for (col = 0; col < width; col++) {
1066
1067 /* set texel to 255 if bit is set */
1068 destRow[comp] =(*src & mask) ? 255 : 0;
1069 destRow += cpp;
1070
1071 if (mask == 1U) {
1072 src++;
1073 mask = 128U;
1074 }
1075 else {
1076 mask = mask >> 1;
1077 }
1078 }
1079
1080 /* get ready for next row */
1081 if (mask != 128)
1082 src++;
1083 }
1084
1085 } /* row */
1086
1087 /* Release surface */
1088 pipe_surface_unmap(surface);
1089 pipe_surface_reference(&surface, NULL);
1090
1091 pt->format = format;
1092
1093 return pt;
1094 }
1095
1096
1097
1098 static void
1099 st_Bitmap(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
1100 const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap )
1101 {
1102 struct st_fragment_program *stfp;
1103 struct st_vertex_program *stvp;
1104 struct st_context *st = ctx->st;
1105 struct pipe_texture *pt;
1106
1107 stvp = make_vertex_shader(ctx->st, GL_TRUE);
1108 stfp = combined_bitmap_fragment_program(ctx);
1109
1110 st_validate_state(st);
1111
1112 pt = make_bitmap_texture(ctx, width, height, unpack, bitmap);
1113 if (pt) {
1114 draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2],
1115 width, height, 1.0, 1.0,
1116 pt, stvp, stfp,
1117 ctx->Current.RasterColor, GL_FALSE);
1118
1119 st->pipe->texture_release(st->pipe, &pt);
1120 }
1121 }
1122
1123
1124 static void
1125 copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy,
1126 GLsizei width, GLsizei height,
1127 GLint dstx, GLint dsty)
1128 {
1129 struct st_renderbuffer *rbRead = st_renderbuffer(ctx->ReadBuffer->_StencilBuffer);
1130 struct st_renderbuffer *rbDraw = st_renderbuffer(ctx->DrawBuffer->_StencilBuffer);
1131 struct pipe_surface *psRead = rbRead->surface;
1132 struct pipe_surface *psDraw = rbDraw->surface;
1133 ubyte *readMap, *drawMap;
1134 ubyte *buffer;
1135 int i;
1136
1137 buffer = malloc(width * height * sizeof(ubyte));
1138 if (!buffer) {
1139 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels(stencil)");
1140 return;
1141 }
1142
1143 /* map the stencil buffers */
1144 readMap = pipe_surface_map(psRead);
1145 drawMap = pipe_surface_map(psDraw);
1146
1147 /* this will do stencil pixel transfer ops */
1148 st_read_stencil_pixels(ctx, srcx, srcy, width, height, GL_UNSIGNED_BYTE,
1149 &ctx->DefaultPacking, buffer);
1150
1151 /* draw */
1152 /* XXX PixelZoom not handled yet */
1153 for (i = 0; i < height; i++) {
1154 ubyte *dst;
1155 const ubyte *src;
1156 int y;
1157
1158 y = dsty + i;
1159
1160 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
1161 y = ctx->DrawBuffer->Height - y - 1;
1162 }
1163
1164 dst = drawMap + (y * psDraw->pitch + dstx) * psDraw->cpp;
1165 src = buffer + i * width;
1166
1167 switch (psDraw->format) {
1168 case PIPE_FORMAT_S8Z24_UNORM:
1169 {
1170 uint *dst4 = (uint *) dst;
1171 int j;
1172 for (j = 0; j < width; j++) {
1173 *dst4 = (*dst4 & 0xffffff) | (src[j] << 24);
1174 dst4++;
1175 }
1176 }
1177 break;
1178 case PIPE_FORMAT_U_S8:
1179 memcpy(dst, src, width);
1180 break;
1181 default:
1182 assert(0);
1183 }
1184 }
1185
1186 free(buffer);
1187
1188 /* unmap the stencil buffers */
1189 pipe_surface_unmap(psRead);
1190 pipe_surface_unmap(psDraw);
1191 }
1192
1193
1194 static void
1195 st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
1196 GLsizei width, GLsizei height,
1197 GLint dstx, GLint dsty, GLenum type)
1198 {
1199 struct st_context *st = ctx->st;
1200 struct pipe_context *pipe = st->pipe;
1201 struct st_renderbuffer *rbRead;
1202 struct st_vertex_program *stvp;
1203 struct st_fragment_program *stfp;
1204 struct pipe_surface *psRead;
1205 struct pipe_surface *psTex;
1206 struct pipe_texture *pt;
1207 GLfloat *color;
1208 uint format;
1209
1210 /* make sure rendering has completed */
1211 pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE);
1212
1213 st_validate_state(st);
1214
1215 if (type == GL_STENCIL) {
1216 /* can't use texturing to do stencil */
1217 copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty);
1218 return;
1219 }
1220
1221 if (type == GL_COLOR) {
1222 rbRead = st_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer);
1223 color = NULL;
1224 stfp = combined_drawpix_fragment_program(ctx);
1225 stvp = make_vertex_shader(ctx->st, GL_FALSE);
1226 }
1227 else {
1228 rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer);
1229 color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
1230 stfp = make_fragment_shader_z(ctx->st);
1231 stvp = make_vertex_shader(ctx->st, GL_TRUE);
1232 }
1233
1234 psRead = rbRead->surface;
1235 format = psRead->format;
1236
1237 pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, format, 0, 0, width, height,
1238 1, 0);
1239 if (!pt)
1240 return;
1241
1242 psTex = pipe->get_tex_surface(pipe, pt, 0, 0, 0);
1243
1244 if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
1245 srcy = ctx->DrawBuffer->Height - srcy - height;
1246 }
1247
1248 /* For some drivers (like Xlib) it's not possible to treat the
1249 * front/back color buffers as surfaces (they're XImages and Pixmaps).
1250 * So, this var tells us if we can use surface_copy here...
1251 */
1252 if (st->haveFramebufferSurfaces) {
1253 /* copy source framebuffer surface into mipmap/texture */
1254 pipe->surface_copy(pipe,
1255 psTex, /* dest */
1256 0, 0, /* destx/y */
1257 psRead,
1258 srcx, srcy, width, height);
1259 }
1260 else {
1261 /* alternate path using get/put_tile() */
1262 GLfloat *buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
1263
1264 (void) pipe_surface_map(psRead);
1265 (void) pipe_surface_map(psTex);
1266
1267 pipe->get_tile_rgba(pipe, psRead, srcx, srcy, width, height, buf);
1268 pipe->put_tile_rgba(pipe, psTex, 0, 0, width, height, buf);
1269
1270 pipe_surface_unmap(psRead);
1271 pipe_surface_unmap(psTex);
1272
1273 free(buf);
1274 }
1275
1276 /* draw textured quad */
1277 draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2],
1278 width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
1279 pt, stvp, stfp, color, GL_TRUE);
1280
1281 pipe_surface_reference(&psTex, NULL);
1282 st->pipe->texture_release(st->pipe, &pt);
1283 }
1284
1285
1286
1287 void st_init_drawpixels_functions(struct dd_function_table *functions)
1288 {
1289 functions->DrawPixels = st_DrawPixels;
1290 functions->CopyPixels = st_CopyPixels;
1291 functions->Bitmap = st_Bitmap;
1292 }