c41bbc59b906322a3417d27005191cedacaa7b7f
[mesa.git] / src / mesa / pipe / softpipe / sp_surface.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 #include "pipe/p_defines.h"
29 #include "pipe/p_util.h"
30 #include "pipe/p_inlines.h"
31 #include "pipe/p_winsys.h"
32 #include "sp_context.h"
33 #include "sp_state.h"
34 #include "sp_surface.h"
35 #include "sp_tile_cache.h"
36
37 /**
38 * Softpipe surface functions.
39 */
40
41
42 /** Convert GLshort in [-32768,32767] to GLfloat in [-1.0,1.0] */
43 #define SHORT_TO_FLOAT(S) ((2.0F * (S) + 1.0F) * (1.0F/65535.0F))
44
45 #define UNCLAMPED_FLOAT_TO_SHORT(us, f) \
46 us = ( (short) ( CLAMP((f), -1.0, 1.0) * 32767.0F) )
47
48
49
50 #if 0
51 #define CLIP_TILE \
52 do { \
53 assert(x + w <= ps->width); \
54 assert(y + h <= ps->height); \
55 } while(0)
56
57 #else
58 #define CLIP_TILE \
59 do { \
60 if (x >= ps->width) \
61 return; \
62 if (y >= ps->height) \
63 return; \
64 if (x + w > ps->width) \
65 w = ps->width - x; \
66 if (y + h > ps->height) \
67 h = ps->height -y; \
68 } while(0)
69 #endif
70
71
72 /*** PIPE_FORMAT_U_A8_R8_G8_B8 ***/
73
74 static void
75 a8r8g8b8_get_tile(struct pipe_surface *ps,
76 unsigned x, unsigned y, unsigned w, unsigned h, float *p)
77 {
78 const unsigned *src
79 = ((const unsigned *) (ps->region->map + ps->offset))
80 + y * ps->pitch + x;
81 unsigned i, j;
82 unsigned w0 = w;
83
84 assert(ps->format == PIPE_FORMAT_U_A8_R8_G8_B8);
85
86 CLIP_TILE;
87
88 for (i = 0; i < h; i++) {
89 float *pRow = p;
90 for (j = 0; j < w; j++) {
91 const unsigned pixel = src[j];
92 pRow[0] = UBYTE_TO_FLOAT((pixel >> 16) & 0xff);
93 pRow[1] = UBYTE_TO_FLOAT((pixel >> 8) & 0xff);
94 pRow[2] = UBYTE_TO_FLOAT((pixel >> 0) & 0xff);
95 pRow[3] = UBYTE_TO_FLOAT((pixel >> 24) & 0xff);
96 pRow += 4;
97 }
98 src += ps->pitch;
99 p += w0 * 4;
100 }
101 }
102
103
104 static void
105 a8r8g8b8_put_tile(struct pipe_surface *ps,
106 unsigned x, unsigned y, unsigned w, unsigned h,
107 const float *p)
108 {
109 unsigned *dst
110 = ((unsigned *) (ps->region->map + ps->offset))
111 + y * ps->pitch + x;
112 unsigned i, j;
113 unsigned w0 = w;
114
115 assert(ps->format == PIPE_FORMAT_U_A8_R8_G8_B8);
116
117 CLIP_TILE;
118
119 for (i = 0; i < h; i++) {
120 const float *pRow = p;
121 for (j = 0; j < w; j++) {
122 unsigned r, g, b, a;
123 UNCLAMPED_FLOAT_TO_UBYTE(r, pRow[0]);
124 UNCLAMPED_FLOAT_TO_UBYTE(g, pRow[1]);
125 UNCLAMPED_FLOAT_TO_UBYTE(b, pRow[2]);
126 UNCLAMPED_FLOAT_TO_UBYTE(a, pRow[3]);
127 dst[j] = (a << 24) | (r << 16) | (g << 8) | b;
128 pRow += 4;
129 }
130 dst += ps->pitch;
131 p += w0 * 4;
132 }
133 }
134
135
136 /*** PIPE_FORMAT_U_B8_G8_R8_A8 ***/
137
138 static void
139 b8g8r8a8_get_tile(struct pipe_surface *ps,
140 unsigned x, unsigned y, unsigned w, unsigned h, float *p)
141 {
142 const unsigned *src
143 = ((const unsigned *) (ps->region->map + ps->offset))
144 + y * ps->pitch + x;
145 unsigned i, j;
146 unsigned w0 = w;
147
148 assert(ps->format == PIPE_FORMAT_U_B8_G8_R8_A8);
149
150 CLIP_TILE;
151
152 for (i = 0; i < h; i++) {
153 float *pRow = p;
154 for (j = 0; j < w; j++) {
155 const unsigned pixel = src[j];
156 pRow[0] = UBYTE_TO_FLOAT((pixel >> 8) & 0xff);
157 pRow[1] = UBYTE_TO_FLOAT((pixel >> 16) & 0xff);
158 pRow[2] = UBYTE_TO_FLOAT((pixel >> 24) & 0xff);
159 pRow[3] = UBYTE_TO_FLOAT((pixel >> 0) & 0xff);
160 pRow += 4;
161 }
162 src += ps->pitch;
163 p += w0 * 4;
164 }
165 }
166
167
168 static void
169 b8g8r8a8_put_tile(struct pipe_surface *ps,
170 unsigned x, unsigned y, unsigned w, unsigned h,
171 const float *p)
172 {
173 unsigned *dst
174 = ((unsigned *) (ps->region->map + ps->offset))
175 + y * ps->pitch + x;
176 unsigned i, j;
177 unsigned w0 = w;
178
179 assert(ps->format == PIPE_FORMAT_U_B8_G8_R8_A8);
180
181 CLIP_TILE;
182
183 for (i = 0; i < h; i++) {
184 const float *pRow = p;
185 for (j = 0; j < w; j++) {
186 unsigned r, g, b, a;
187 UNCLAMPED_FLOAT_TO_UBYTE(r, pRow[0]);
188 UNCLAMPED_FLOAT_TO_UBYTE(g, pRow[1]);
189 UNCLAMPED_FLOAT_TO_UBYTE(b, pRow[2]);
190 UNCLAMPED_FLOAT_TO_UBYTE(a, pRow[3]);
191 dst[j] = (b << 24) | (g << 16) | (r << 8) | a;
192 pRow += 4;
193 }
194 dst += ps->pitch;
195 p += w0 * 4;
196 }
197 }
198
199
200 /*** PIPE_FORMAT_U_A1_R5_G5_B5 ***/
201
202 static void
203 a1r5g5b5_get_tile(struct pipe_surface *ps,
204 unsigned x, unsigned y, unsigned w, unsigned h, float *p)
205 {
206 const ushort *src
207 = ((const ushort *) (ps->region->map + ps->offset))
208 + y * ps->pitch + x;
209 unsigned i, j;
210
211 assert(ps->format == PIPE_FORMAT_U_A1_R5_G5_B5);
212
213 for (i = 0; i < h; i++) {
214 for (j = 0; j < w; j++) {
215 const ushort pixel = src[j];
216 p[0] = ((pixel >> 10) & 0x1f) * (1.0f / 31.0f);
217 p[1] = ((pixel >> 5) & 0x1f) * (1.0f / 31.0f);
218 p[2] = ((pixel ) & 0x1f) * (1.0f / 31.0f);
219 p[3] = ((pixel >> 15) ) * 1.0f;
220 p += 4;
221 }
222 src += ps->pitch;
223 }
224 }
225
226
227
228 /*** PIPE_FORMAT_U_Z16 ***/
229
230 /**
231 * Return each Z value as four floats in [0,1].
232 */
233 static void
234 z16_get_tile(struct pipe_surface *ps,
235 unsigned x, unsigned y, unsigned w, unsigned h, float *p)
236 {
237 const ushort *src
238 = ((const ushort *) (ps->region->map + ps->offset))
239 + y * ps->pitch + x;
240 const float scale = 1.0f / 65535.0f;
241 unsigned i, j;
242 unsigned w0 = w;
243
244 assert(ps->format == PIPE_FORMAT_U_Z16);
245
246 CLIP_TILE;
247
248 for (i = 0; i < h; i++) {
249 float *pRow = p;
250 for (j = 0; j < w; j++) {
251 pRow[j * 4 + 0] =
252 pRow[j * 4 + 1] =
253 pRow[j * 4 + 2] =
254 pRow[j * 4 + 3] = src[j] * scale;
255 }
256 src += ps->pitch;
257 p += 4 * w0;
258 }
259 }
260
261
262
263
264 /*** PIPE_FORMAT_U_L8 ***/
265
266 static void
267 l8_get_tile(struct pipe_surface *ps,
268 unsigned x, unsigned y, unsigned w, unsigned h, float *p)
269 {
270 const ubyte *src
271 = ((const ubyte *) (ps->region->map + ps->offset))
272 + y * ps->pitch + x;
273 unsigned i, j;
274 unsigned w0 = w;
275
276 assert(ps->format == PIPE_FORMAT_U_L8);
277
278 CLIP_TILE;
279
280 for (i = 0; i < h; i++) {
281 float *pRow = p;
282 for (j = 0; j < w; j++) {
283 pRow[0] =
284 pRow[1] =
285 pRow[2] = UBYTE_TO_FLOAT(src[j]);
286 pRow[3] = 1.0;
287 pRow += 4;
288 }
289 src += ps->pitch;
290 p += w0 * 4;
291 }
292 }
293
294
295 /*** PIPE_FORMAT_U_A8 ***/
296
297 static void
298 a8_get_tile(struct pipe_surface *ps,
299 unsigned x, unsigned y, unsigned w, unsigned h, float *p)
300 {
301 const ubyte *src
302 = ((const ubyte *) (ps->region->map + ps->offset))
303 + y * ps->pitch + x;
304 unsigned i, j;
305 unsigned w0 = w;
306
307 assert(ps->format == PIPE_FORMAT_U_A8);
308
309 CLIP_TILE;
310
311 for (i = 0; i < h; i++) {
312 float *pRow = p;
313 for (j = 0; j < w; j++) {
314 pRow[0] =
315 pRow[1] =
316 pRow[2] = 0.0;
317 pRow[3] = UBYTE_TO_FLOAT(src[j]);
318 pRow += 4;
319 }
320 src += ps->pitch;
321 p += w0 * 4;
322 }
323 }
324
325
326 /*** PIPE_FORMAT_S_R16_G16_B16_A16 ***/
327
328 static void
329 r16g16b16a16_get_tile(struct pipe_surface *ps,
330 unsigned x, unsigned y, unsigned w, unsigned h, float *p)
331 {
332 const short *src
333 = ((const short *) (ps->region->map + ps->offset))
334 + (y * ps->pitch + x) * 4;
335 unsigned i, j;
336 unsigned w0 = w;
337
338 assert(ps->format == PIPE_FORMAT_S_R16_G16_B16_A16);
339
340 CLIP_TILE;
341
342 for (i = 0; i < h; i++) {
343 float *pRow = p;
344 const short *pixel = src;
345 for (j = 0; j < w; j++) {
346 pRow[0] = SHORT_TO_FLOAT(pixel[0]);
347 pRow[1] = SHORT_TO_FLOAT(pixel[1]);
348 pRow[2] = SHORT_TO_FLOAT(pixel[2]);
349 pRow[3] = SHORT_TO_FLOAT(pixel[3]);
350 pRow += 4;
351 pixel += 4;
352 }
353 src += ps->pitch * 4;
354 p += w0 * 4;
355 }
356 }
357
358
359 static void
360 r16g16b16a16_put_tile(struct pipe_surface *ps,
361 unsigned x, unsigned y, unsigned w, unsigned h,
362 const float *p)
363 {
364 short *dst
365 = ((short *) (ps->region->map + ps->offset))
366 + (y * ps->pitch + x) * 4;
367 unsigned i, j;
368 unsigned w0 = w;
369
370 assert(ps->format == PIPE_FORMAT_S_R16_G16_B16_A16);
371
372 CLIP_TILE;
373
374 for (i = 0; i < h; i++) {
375 const float *pRow = p;
376 for (j = 0; j < w; j++) {
377 short r, g, b, a;
378 UNCLAMPED_FLOAT_TO_SHORT(r, pRow[0]);
379 UNCLAMPED_FLOAT_TO_SHORT(g, pRow[1]);
380 UNCLAMPED_FLOAT_TO_SHORT(b, pRow[2]);
381 UNCLAMPED_FLOAT_TO_SHORT(a, pRow[3]);
382 dst[j*4+0] = r;
383 dst[j*4+1] = g;
384 dst[j*4+2] = b;
385 dst[j*4+3] = a;
386 pRow += 4;
387 }
388 dst += ps->pitch * 4;
389 p += w0 * 4;
390 }
391 }
392
393
394
395 /*** PIPE_FORMAT_U_I8 ***/
396
397 static void
398 i8_get_tile(struct pipe_surface *ps,
399 unsigned x, unsigned y, unsigned w, unsigned h, float *p)
400 {
401 const ubyte *src
402 = ((const ubyte *) (ps->region->map + ps->offset))
403 + y * ps->pitch + x;
404 unsigned i, j;
405 unsigned w0 = w;
406
407 assert(ps->format == PIPE_FORMAT_U_I8);
408
409 CLIP_TILE;
410
411 for (i = 0; i < h; i++) {
412 float *pRow = p;
413 for (j = 0; j < w; j++) {
414 pRow[0] =
415 pRow[1] =
416 pRow[2] =
417 pRow[3] = UBYTE_TO_FLOAT(src[j]);
418 pRow += 4;
419 }
420 src += ps->pitch;
421 p += w0 * 4;
422 }
423 }
424
425
426 /*** PIPE_FORMAT_U_A8_L8 ***/
427
428 static void
429 a8_l8_get_tile(struct pipe_surface *ps,
430 unsigned x, unsigned y, unsigned w, unsigned h, float *p)
431 {
432 const ushort *src
433 = ((const ushort *) (ps->region->map + ps->offset))
434 + y * ps->pitch + x;
435 unsigned i, j;
436 unsigned w0 = w;
437
438 assert(ps->format == PIPE_FORMAT_U_A8_L8);
439
440 CLIP_TILE;
441
442 for (i = 0; i < h; i++) {
443 float *pRow = p;
444 for (j = 0; j < w; j++) {
445 const ushort p = src[j];
446 pRow[0] =
447 pRow[1] =
448 pRow[2] = UBYTE_TO_FLOAT(p & 0xff);
449 pRow[3] = UBYTE_TO_FLOAT(p >> 8);
450 pRow += 4;
451 }
452 src += ps->pitch;
453 p += w0 * 4;
454 }
455 }
456
457
458
459
460 /*** PIPE_FORMAT_U_Z32 ***/
461
462 /**
463 * Return each Z value as four floats in [0,1].
464 */
465 static void
466 z32_get_tile(struct pipe_surface *ps,
467 unsigned x, unsigned y, unsigned w, unsigned h, float *p)
468 {
469 const uint *src
470 = ((const uint *) (ps->region->map + ps->offset))
471 + y * ps->pitch + x;
472 const double scale = 1.0 / (double) 0xffffffff;
473 unsigned i, j;
474 unsigned w0 = w;
475
476 assert(ps->format == PIPE_FORMAT_U_Z16);
477
478 CLIP_TILE;
479
480 for (i = 0; i < h; i++) {
481 float *pRow = p;
482 for (j = 0; j < w; j++) {
483 pRow[j * 4 + 0] =
484 pRow[j * 4 + 1] =
485 pRow[j * 4 + 2] =
486 pRow[j * 4 + 3] = (float) (scale * src[j]);
487 }
488 src += ps->pitch;
489 p += 4 * w0;
490 }
491 }
492
493
494 /*** PIPE_FORMAT_S8_Z24 ***/
495
496 /**
497 * Return Z component as four float in [0,1]. Stencil part ignored.
498 */
499 static void
500 s8z24_get_tile(struct pipe_surface *ps,
501 unsigned x, unsigned y, unsigned w, unsigned h, float *p)
502 {
503 const uint *src
504 = ((const uint *) (ps->region->map + ps->offset))
505 + y * ps->pitch + x;
506 const double scale = 1.0 / ((1 << 24) - 1);
507 unsigned i, j;
508 unsigned w0 = w;
509
510 assert(ps->format == PIPE_FORMAT_S8_Z24);
511
512 CLIP_TILE;
513
514 for (i = 0; i < h; i++) {
515 float *pRow = p;
516 for (j = 0; j < w; j++) {
517 pRow[j * 4 + 0] =
518 pRow[j * 4 + 1] =
519 pRow[j * 4 + 2] =
520 pRow[j * 4 + 3] = (float) (scale * (src[j] & 0xffffff));
521 }
522 src += ps->pitch;
523 p += 4 * w0;
524 }
525 }
526
527
528 /*** PIPE_FORMAT_Z24_S8 ***/
529
530 /**
531 * Return Z component as four float in [0,1]. Stencil part ignored.
532 */
533 static void
534 z24s8_get_tile(struct pipe_surface *ps,
535 unsigned x, unsigned y, unsigned w, unsigned h, float *p)
536 {
537 const uint *src
538 = ((const uint *) (ps->region->map + ps->offset))
539 + y * ps->pitch + x;
540 const double scale = 1.0 / ((1 << 24) - 1);
541 unsigned i, j;
542 unsigned w0 = w;
543
544 assert(ps->format == PIPE_FORMAT_Z24_S8);
545
546 CLIP_TILE;
547
548 for (i = 0; i < h; i++) {
549 float *pRow = p;
550 for (j = 0; j < w; j++) {
551 pRow[j * 4 + 0] =
552 pRow[j * 4 + 1] =
553 pRow[j * 4 + 2] =
554 pRow[j * 4 + 3] = (float) (scale * (src[j] >> 8));
555 }
556 src += ps->pitch;
557 p += 4 * w0;
558 }
559 }
560
561
562 /**
563 * Called via pipe->get_tex_surface()
564 * XXX is this in the right place?
565 */
566 struct pipe_surface *
567 softpipe_get_tex_surface(struct pipe_context *pipe,
568 struct pipe_texture *pt,
569 unsigned face, unsigned level, unsigned zslice)
570 {
571 struct softpipe_texture *spt = (struct softpipe_texture *)pt;
572 struct pipe_surface *ps;
573 unsigned offset; /* in bytes */
574
575 offset = spt->level_offset[level];
576
577 if (pt->target == PIPE_TEXTURE_CUBE) {
578 offset += spt->image_offset[level][face] * pt->cpp;
579 }
580 else if (pt->target == PIPE_TEXTURE_3D) {
581 offset += spt->image_offset[level][zslice] * pt->cpp;
582 }
583 else {
584 assert(face == 0);
585 assert(zslice == 0);
586 }
587
588 ps = pipe->winsys->surface_alloc(pipe->winsys, pt->format);
589 if (ps) {
590 assert(ps->format);
591 assert(ps->refcount);
592 pipe_region_reference(&ps->region, spt->region);
593 ps->cpp = pt->cpp;
594 ps->width = pt->width[level];
595 ps->height = pt->height[level];
596 ps->pitch = spt->pitch;
597 ps->offset = offset;
598 }
599 return ps;
600 }
601
602
603 /**
604 * Move raw block of pixels from surface to user memory.
605 */
606 void
607 softpipe_get_tile(struct pipe_context *pipe, struct pipe_surface *ps,
608 uint x, uint y, uint w, uint h,
609 void *p, int dst_stride)
610 {
611 const uint cpp = ps->cpp;
612 const ubyte *pSrc;
613 ubyte *pDest;
614 uint i;
615
616 assert(ps->region->map);
617
618 if (dst_stride == 0) {
619 dst_stride = w * cpp;
620 }
621
622 CLIP_TILE;
623
624 pSrc = ps->region->map + ps->offset + (y * ps->pitch + x) * cpp;
625 pDest = (ubyte *) p;
626
627 for (i = 0; i < h; i++) {
628 memcpy(pDest, pSrc, w * cpp);
629 pDest += dst_stride;
630 pSrc += ps->pitch * cpp;
631 }
632 }
633
634
635 /**
636 * Move raw block of pixels from user memory to surface.
637 */
638 void
639 softpipe_put_tile(struct pipe_context *pipe, struct pipe_surface *ps,
640 uint x, uint y, uint w, uint h,
641 const void *p, int src_stride)
642 {
643 const uint cpp = ps->cpp;
644 const ubyte *pSrc;
645 ubyte *pDest;
646 uint i;
647
648 assert(ps->region->map);
649
650 if (src_stride == 0) {
651 src_stride = w * cpp;
652 }
653
654 CLIP_TILE;
655
656 pSrc = (const ubyte *) p;
657 pDest = ps->region->map + ps->offset + (y * ps->pitch + x) * cpp;
658
659 for (i = 0; i < h; i++) {
660 memcpy(pDest, pSrc, w * cpp);
661 pDest += ps->pitch * cpp;
662 pSrc += src_stride;
663 }
664 }
665
666
667 /* XXX TEMPORARY */
668 void
669 softpipe_get_tile_rgba(struct pipe_context *pipe,
670 struct pipe_surface *ps,
671 uint x, uint y, uint w, uint h,
672 float *p)
673 {
674 switch (ps->format) {
675 case PIPE_FORMAT_U_A8_R8_G8_B8:
676 a8r8g8b8_get_tile(ps, x, y, w, h, p);
677 break;
678 case PIPE_FORMAT_U_B8_G8_R8_A8:
679 b8g8r8a8_get_tile(ps, x, y, w, h, p);
680 break;
681 case PIPE_FORMAT_U_A1_R5_G5_B5:
682 a1r5g5b5_get_tile(ps, x, y, w, h, p);
683 break;
684 case PIPE_FORMAT_U_L8:
685 l8_get_tile(ps, x, y, w, h, p);
686 break;
687 case PIPE_FORMAT_U_A8:
688 a8_get_tile(ps, x, y, w, h, p);
689 break;
690 case PIPE_FORMAT_U_I8:
691 i8_get_tile(ps, x, y, w, h, p);
692 break;
693 case PIPE_FORMAT_U_A8_L8:
694 a8_l8_get_tile(ps, x, y, w, h, p);
695 break;
696 case PIPE_FORMAT_S_R16_G16_B16_A16:
697 r16g16b16a16_get_tile(ps, x, y, w, h, p);
698 break;
699 case PIPE_FORMAT_U_Z16:
700 z16_get_tile(ps, x, y, w, h, p);
701 break;
702 case PIPE_FORMAT_U_Z32:
703 z32_get_tile(ps, x, y, w, h, p);
704 break;
705 case PIPE_FORMAT_S8_Z24:
706 s8z24_get_tile(ps, x, y, w, h, p);
707 break;
708 case PIPE_FORMAT_Z24_S8:
709 z24s8_get_tile(ps, x, y, w, h, p);
710 break;
711 default:
712 assert(0);
713 }
714 }
715
716
717 /* XXX TEMPORARY */
718 void
719 softpipe_put_tile_rgba(struct pipe_context *pipe,
720 struct pipe_surface *ps,
721 uint x, uint y, uint w, uint h,
722 const float *p)
723 {
724 switch (ps->format) {
725 case PIPE_FORMAT_U_A8_R8_G8_B8:
726 a8r8g8b8_put_tile(ps, x, y, w, h, p);
727 break;
728 case PIPE_FORMAT_U_B8_G8_R8_A8:
729 b8g8r8a8_put_tile(ps, x, y, w, h, p);
730 break;
731 case PIPE_FORMAT_U_A1_R5_G5_B5:
732 /*a1r5g5b5_put_tile(ps, x, y, w, h, p);*/
733 break;
734 case PIPE_FORMAT_U_L8:
735 /*l8_put_tile(ps, x, y, w, h, p);*/
736 break;
737 case PIPE_FORMAT_U_A8:
738 /*a8_put_tile(ps, x, y, w, h, p);*/
739 break;
740 case PIPE_FORMAT_U_I8:
741 /*i8_put_tile(ps, x, y, w, h, p);*/
742 break;
743 case PIPE_FORMAT_U_A8_L8:
744 /*a8_l8_put_tile(ps, x, y, w, h, p);*/
745 break;
746 case PIPE_FORMAT_S_R16_G16_B16_A16:
747 r16g16b16a16_put_tile(ps, x, y, w, h, p);
748 break;
749 case PIPE_FORMAT_U_Z16:
750 /*z16_put_tile(ps, x, y, w, h, p);*/
751 break;
752 case PIPE_FORMAT_U_Z32:
753 /*z32_put_tile(ps, x, y, w, h, p);*/
754 break;
755 case PIPE_FORMAT_S8_Z24:
756 /*s8z24_put_tile(ps, x, y, w, h, p);*/
757 break;
758 case PIPE_FORMAT_Z24_S8:
759 /*z24s8_put_tile(ps, x, y, w, h, p);*/
760 break;
761 default:
762 assert(0);
763 }
764 }
765
766
767 /**
768 * Copy 2D rect from one place to another.
769 * Position and sizes are in pixels.
770 */
771 static void
772 copy_rect(ubyte * dst,
773 unsigned cpp,
774 unsigned dst_pitch,
775 unsigned dst_x,
776 unsigned dst_y,
777 unsigned width,
778 unsigned height,
779 const ubyte * src,
780 unsigned src_pitch,
781 unsigned src_x,
782 unsigned src_y)
783 {
784 unsigned i;
785
786 dst_pitch *= cpp;
787 src_pitch *= cpp;
788 dst += dst_x * cpp;
789 src += src_x * cpp;
790 dst += dst_y * dst_pitch;
791 src += src_y * src_pitch;
792 width *= cpp;
793
794 if (width == dst_pitch && width == src_pitch)
795 memcpy(dst, src, height * width);
796 else {
797 for (i = 0; i < height; i++) {
798 memcpy(dst, src, width);
799 dst += dst_pitch;
800 src += src_pitch;
801 }
802 }
803 }
804
805
806 /* Upload data to a rectangular sub-region. Lots of choices how to do this:
807 *
808 * - memcpy by span to current destination
809 * - upload data as new buffer and blit
810 *
811 * Currently always memcpy.
812 */
813 static void
814 sp_surface_data(struct pipe_context *pipe,
815 struct pipe_surface *dst,
816 unsigned dstx, unsigned dsty,
817 const void *src, unsigned src_pitch,
818 unsigned srcx, unsigned srcy, unsigned width, unsigned height)
819 {
820 copy_rect(pipe->region_map(pipe, dst->region) + dst->offset,
821 dst->cpp,
822 dst->pitch,
823 dstx, dsty, width, height, src, src_pitch, srcx, srcy);
824
825 pipe->region_unmap(pipe, dst->region);
826 }
827
828 /* Assumes all values are within bounds -- no checking at this level -
829 * do it higher up if required.
830 */
831 static void
832 sp_surface_copy(struct pipe_context *pipe,
833 struct pipe_surface *dst,
834 unsigned dstx, unsigned dsty,
835 struct pipe_surface *src,
836 unsigned srcx, unsigned srcy, unsigned width, unsigned height)
837 {
838 ubyte *src_map, *dst_map;
839 assert( dst->cpp == src->cpp );
840
841 dst_map = pipe->region_map(pipe, dst->region);
842 src_map = pipe->region_map(pipe, src->region);
843 copy_rect(dst_map + dst->offset,
844 dst->cpp,
845 dst->pitch,
846 dstx, dsty,
847 width, height,
848 src_map + src->offset,
849 src->pitch,
850 srcx, srcy);
851
852 pipe->region_unmap(pipe, src->region);
853 pipe->region_unmap(pipe, dst->region);
854 }
855
856
857 static ubyte *
858 get_pointer(struct pipe_surface *dst, unsigned x, unsigned y)
859 {
860 return dst->region->map + (y * dst->pitch + x) * dst->cpp;
861 }
862
863
864 #define UBYTE_TO_USHORT(B) ((B) | ((B) << 8))
865
866
867 /**
868 * Fill a rectangular sub-region. Need better logic about when to
869 * push buffers into AGP - will currently do so whenever possible.
870 */
871 static void
872 sp_surface_fill(struct pipe_context *pipe,
873 struct pipe_surface *dst,
874 unsigned dstx, unsigned dsty,
875 unsigned width, unsigned height, unsigned value)
876 {
877 unsigned i, j;
878
879 assert(dst->pitch > 0);
880 assert(width <= dst->pitch);
881
882 (void)pipe->region_map(pipe, dst->region);
883
884 switch (dst->cpp) {
885 case 1:
886 {
887 ubyte *row = get_pointer(dst, dstx, dsty);
888 for (i = 0; i < height; i++) {
889 memset(row, value, width);
890 row += dst->pitch;
891 }
892 }
893 break;
894 case 2:
895 {
896 ushort *row = (ushort *) get_pointer(dst, dstx, dsty);
897 for (i = 0; i < height; i++) {
898 for (j = 0; j < width; j++)
899 row[j] = (ushort) value;
900 row += dst->pitch;
901 }
902 }
903 break;
904 case 4:
905 {
906 unsigned *row = (unsigned *) get_pointer(dst, dstx, dsty);
907 for (i = 0; i < height; i++) {
908 for (j = 0; j < width; j++)
909 row[j] = value;
910 row += dst->pitch;
911 }
912 }
913 break;
914 case 8:
915 {
916 /* expand the 4-byte clear value to an 8-byte value */
917 ushort *row = (ushort *) get_pointer(dst, dstx, dsty);
918 ushort val0 = UBYTE_TO_USHORT((value >> 0) & 0xff);
919 ushort val1 = UBYTE_TO_USHORT((value >> 8) & 0xff);
920 ushort val2 = UBYTE_TO_USHORT((value >> 16) & 0xff);
921 ushort val3 = UBYTE_TO_USHORT((value >> 24) & 0xff);
922 for (i = 0; i < height; i++) {
923 for (j = 0; j < width; j++) {
924 row[j*4+0] = val0;
925 row[j*4+1] = val1;
926 row[j*4+2] = val2;
927 row[j*4+3] = val3;
928 }
929 row += dst->pitch * 4;
930 }
931 }
932 break;
933 default:
934 assert(0);
935 break;
936 }
937
938 pipe->region_unmap( pipe, dst->region );
939 }
940
941
942 void
943 sp_init_surface_functions(struct softpipe_context *sp)
944 {
945 sp->pipe.get_tile = softpipe_get_tile;
946 sp->pipe.put_tile = softpipe_put_tile;
947
948 sp->pipe.get_tile_rgba = softpipe_get_tile_rgba;
949 sp->pipe.put_tile_rgba = softpipe_put_tile_rgba;
950
951 sp->pipe.surface_data = sp_surface_data;
952 sp->pipe.surface_copy = sp_surface_copy;
953 sp->pipe.surface_fill = sp_surface_fill;
954 }