sp_surface.c revision 4ddd65967915ca4846f2831bc676c878a29dae4a
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 "util/p_tile.h"
33#include "sp_context.h"
34#include "sp_surface.h"
35
36
37
38/**
39 * Copy a rectangular region from one surface to another.
40 * Surfaces must have same bpp.
41 *
42 * Assumes all values are within bounds -- no checking at this level -
43 * do it higher up if required.
44 */
45static void
46sp_surface_copy(struct pipe_context *pipe,
47                boolean do_flip,
48		struct pipe_surface *dst,
49		unsigned dstx, unsigned dsty,
50		struct pipe_surface *src,
51		unsigned srcx, unsigned srcy, unsigned width, unsigned height)
52{
53   void *dst_map = pipe->screen->surface_map( pipe->screen,
54                                              dst,
55                                              PIPE_BUFFER_USAGE_CPU_WRITE );
56
57   const void *src_map = pipe->screen->surface_map( pipe->screen,
58                                                    src,
59                                                    PIPE_BUFFER_USAGE_CPU_READ );
60
61   assert(dst->block.size == src->block.size);
62   assert(dst->block.width == src->block.width);
63   assert(dst->block.height == src->block.height);
64   assert(src_map);
65   assert(dst_map);
66
67   /* If do_flip, invert src_y position and pass negative src stride */
68   pipe_copy_rect(dst_map,
69                  &dst->block,
70                  dst->stride,
71                  dstx, dsty,
72                  width, height,
73                  src_map,
74                  do_flip ? -(int) src->stride : src->stride,
75                  srcx, do_flip ? src->height - 1 - srcy : srcy);
76
77   pipe->screen->surface_unmap(pipe->screen, src);
78   pipe->screen->surface_unmap(pipe->screen, dst);
79}
80
81
82static void *
83get_pointer(struct pipe_surface *dst, void *dst_map, unsigned x, unsigned y)
84{
85   return (char *)dst_map + y / dst->block.height * dst->stride + x / dst->block.width * dst->block.size;
86}
87
88
89#define UBYTE_TO_USHORT(B) ((B) | ((B) << 8))
90
91
92/**
93 * Fill a rectangular sub-region.  Need better logic about when to
94 * push buffers into AGP - will currently do so whenever possible.
95 */
96static void
97sp_surface_fill(struct pipe_context *pipe,
98		struct pipe_surface *dst,
99		unsigned dstx, unsigned dsty,
100		unsigned width, unsigned height, unsigned value)
101{
102   unsigned i, j;
103   void *dst_map = pipe->screen->surface_map( pipe->screen,
104                                              dst,
105                                              PIPE_BUFFER_USAGE_CPU_WRITE );
106
107   assert(dst->stride > 0);
108
109
110   switch (dst->block.size) {
111   case 1:
112   case 2:
113   case 4:
114      pipe_fill_rect(dst_map, &dst->block, dst->stride, dstx, dsty, width, height, value);
115      break;
116   case 8:
117      {
118         /* expand the 4-byte clear value to an 8-byte value */
119         ushort *row = (ushort *) get_pointer(dst, dst_map, dstx, dsty);
120         ushort val0 = UBYTE_TO_USHORT((value >>  0) & 0xff);
121         ushort val1 = UBYTE_TO_USHORT((value >>  8) & 0xff);
122         ushort val2 = UBYTE_TO_USHORT((value >> 16) & 0xff);
123         ushort val3 = UBYTE_TO_USHORT((value >> 24) & 0xff);
124         val0 = (val0 << 8) | val0;
125         val1 = (val1 << 8) | val1;
126         val2 = (val2 << 8) | val2;
127         val3 = (val3 << 8) | val3;
128         for (i = 0; i < height; i++) {
129            for (j = 0; j < width; j++) {
130               row[j*4+0] = val0;
131               row[j*4+1] = val1;
132               row[j*4+2] = val2;
133               row[j*4+3] = val3;
134            }
135            row += dst->stride/2;
136         }
137      }
138      break;
139   default:
140      assert(0);
141      break;
142   }
143
144   pipe->screen->surface_unmap(pipe->screen, dst);
145}
146
147
148void
149sp_init_surface_functions(struct softpipe_context *sp)
150{
151   sp->pipe.surface_copy = sp_surface_copy;
152   sp->pipe.surface_fill = sp_surface_fill;
153}
154