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