b4562f26e6547bc718fc2c2e1806bdc61e94adcb
[mesa.git] / src / mesa / pipe / nv40 / nv40_surface.c
1
2 /**************************************************************************
3 *
4 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sub license, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
17 * of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *
27 **************************************************************************/
28
29 #include "nv40_context.h"
30 #include "pipe/p_defines.h"
31 #include "pipe/p_util.h"
32 #include "pipe/p_winsys.h"
33 #include "pipe/p_inlines.h"
34
35
36 #define CLIP_TILE \
37 do { \
38 if (x >= ps->width) \
39 return; \
40 if (y >= ps->height) \
41 return; \
42 if (x + w > ps->width) \
43 w = ps->width - x; \
44 if (y + h > ps->height) \
45 h = ps->height -y; \
46 } while(0)
47
48
49 /**
50 * Note: this is exactly like a8r8g8b8_get_tile() in sp_surface.c
51 * Share it someday.
52 */
53 static void
54 nv40_get_tile_rgba(struct pipe_context *pipe,
55 struct pipe_surface *ps,
56 uint x, uint y, uint w, uint h, float *p)
57 {
58 const unsigned *src
59 = ((const unsigned *) (ps->map + ps->offset))
60 + y * ps->pitch + x;
61 unsigned i, j;
62 unsigned w0 = w;
63
64 CLIP_TILE;
65
66 switch (ps->format) {
67 case PIPE_FORMAT_A8R8G8B8_UNORM:
68 for (i = 0; i < h; i++) {
69 float *pRow = p;
70 for (j = 0; j < w; j++) {
71 const unsigned pixel = src[j];
72 pRow[0] = UBYTE_TO_FLOAT((pixel >> 16) & 0xff);
73 pRow[1] = UBYTE_TO_FLOAT((pixel >> 8) & 0xff);
74 pRow[2] = UBYTE_TO_FLOAT((pixel >> 0) & 0xff);
75 pRow[3] = UBYTE_TO_FLOAT((pixel >> 24) & 0xff);
76 pRow += 4;
77 }
78 src += ps->pitch;
79 p += w0 * 4;
80 }
81 break;
82 case PIPE_FORMAT_Z24S8_UNORM:
83 {
84 const float scale = 1.0 / (float) 0xffffff;
85 for (i = 0; i < h; i++) {
86 float *pRow = p;
87 for (j = 0; j < w; j++) {
88 const unsigned pixel = src[j];
89 pRow[0] =
90 pRow[1] =
91 pRow[2] =
92 pRow[3] = ((pixel & 0xffffff) >> 8) * scale;
93 pRow += 4;
94 }
95 src += ps->pitch;
96 p += w0 * 4;
97 }
98 }
99 break;
100 default:
101 assert(0);
102 }
103 }
104
105
106 static void
107 nv40_put_tile_rgba(struct pipe_context *pipe,
108 struct pipe_surface *ps,
109 uint x, uint y, uint w, uint h, const float *p)
110 {
111 /* TODO */
112 assert(0);
113 }
114
115
116 /*
117 * XXX note: same as code in sp_surface.c
118 */
119 static void
120 nv40_get_tile(struct pipe_context *pipe,
121 struct pipe_surface *ps,
122 uint x, uint y, uint w, uint h,
123 void *p, int dst_stride)
124 {
125 const uint cpp = ps->cpp;
126 const uint w0 = w;
127 const ubyte *pSrc;
128 ubyte *pDest;
129 uint i;
130
131 assert(ps->map);
132
133 CLIP_TILE;
134
135 if (dst_stride == 0) {
136 dst_stride = w0 * cpp;
137 }
138
139 pSrc = ps->map + ps->offset + (y * ps->pitch + x) * cpp;
140 pDest = (ubyte *) p;
141
142 for (i = 0; i < h; i++) {
143 memcpy(pDest, pSrc, w0 * cpp);
144 pDest += dst_stride;
145 pSrc += ps->pitch * cpp;
146 }
147 }
148
149
150 /*
151 * XXX note: same as code in sp_surface.c
152 */
153 static void
154 nv40_put_tile(struct pipe_context *pipe,
155 struct pipe_surface *ps,
156 uint x, uint y, uint w, uint h,
157 const void *p, int src_stride)
158 {
159 const uint cpp = ps->cpp;
160 const uint w0 = w;
161 const ubyte *pSrc;
162 ubyte *pDest;
163 uint i;
164
165 assert(ps->map);
166
167 CLIP_TILE;
168
169 if (src_stride == 0) {
170 src_stride = w0 * cpp;
171 }
172
173 pSrc = (const ubyte *) p;
174 pDest = ps->map + ps->offset + (y * ps->pitch + x) * cpp;
175
176 for (i = 0; i < h; i++) {
177 memcpy(pDest, pSrc, w0 * cpp);
178 pDest += ps->pitch * cpp;
179 pSrc += src_stride;
180 }
181 }
182
183
184 static struct pipe_surface *
185 nv40_get_tex_surface(struct pipe_context *pipe,
186 struct pipe_texture *pt,
187 unsigned face, unsigned level, unsigned zslice)
188 {
189 struct pipe_winsys *ws = pipe->winsys;
190 struct nv40_miptree *nv40mt = (struct nv40_miptree *)pt;
191 struct pipe_surface *ps;
192
193 ps = ws->surface_alloc(ws, pt->format);
194 if (!ps)
195 return NULL;
196 ws->buffer_reference(ws, &ps->buffer, nv40mt->buffer);
197 ps->cpp = pt->cpp;
198 ps->width = pt->width[level];
199 ps->height = pt->height[level];
200 ps->pitch = nv40mt->level[level].pitch / ps->cpp;
201
202 if (pt->target == PIPE_TEXTURE_CUBE) {
203 ps->offset = nv40mt->level[level].image_offset[face];
204 } else
205 if (pt->target == PIPE_TEXTURE_3D) {
206 ps->offset = nv40mt->level[level].image_offset[zslice];
207 } else {
208 ps->offset = nv40mt->level[level].image_offset[0];
209 }
210
211 return ps;
212 }
213
214 static void
215 nv40_surface_data(struct pipe_context *pipe, struct pipe_surface *dest,
216 unsigned destx, unsigned desty, const void *src,
217 unsigned src_stride, unsigned srcx, unsigned srcy,
218 unsigned width, unsigned height)
219 {
220 struct nv40_context *nv40 = (struct nv40_context *)pipe;
221 struct nouveau_winsys *nvws = nv40->nvws;
222
223 nvws->surface_data(nvws, dest, destx, desty, src, src_stride,
224 srcx, srcy, width, height);
225 }
226
227 static void
228 nv40_surface_copy(struct pipe_context *pipe, struct pipe_surface *dest,
229 unsigned destx, unsigned desty, struct pipe_surface *src,
230 unsigned srcx, unsigned srcy, unsigned width, unsigned height)
231 {
232 struct nv40_context *nv40 = (struct nv40_context *)pipe;
233 struct nouveau_winsys *nvws = nv40->nvws;
234
235 nvws->surface_copy(nvws, dest, destx, desty, src, srcx, srcy,
236 width, height);
237 }
238
239 static void
240 nv40_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest,
241 unsigned destx, unsigned desty, unsigned width,
242 unsigned height, unsigned value)
243 {
244 struct nv40_context *nv40 = (struct nv40_context *)pipe;
245 struct nouveau_winsys *nvws = nv40->nvws;
246
247 nvws->surface_fill(nvws, dest, destx, desty, width, height, value);
248 }
249
250 void
251 nv40_init_surface_functions(struct nv40_context *nv40)
252 {
253 nv40->pipe.get_tex_surface = nv40_get_tex_surface;
254 nv40->pipe.get_tile = nv40_get_tile;
255 nv40->pipe.put_tile = nv40_put_tile;
256 nv40->pipe.get_tile_rgba = nv40_get_tile_rgba;
257 nv40->pipe.put_tile_rgba = nv40_put_tile_rgba;
258 nv40->pipe.surface_data = nv40_surface_data;
259 nv40->pipe.surface_copy = nv40_surface_copy;
260 nv40->pipe.surface_fill = nv40_surface_fill;
261 }