385202507db4cf32992d52785bbb3d3985071136
[mesa.git] / src / mesa / pipe / i915simple / i915_surface.c
1 /**************************************************************************
2 *
3 * Copyright 2003 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 "i915_context.h"
29 #include "i915_blit.h"
30 #include "i915_state.h"
31 #include "pipe/p_defines.h"
32 #include "pipe/p_util.h"
33 #include "pipe/p_inlines.h"
34 #include "pipe/p_winsys.h"
35
36
37 #define CLIP_TILE \
38 do { \
39 if (x >= ps->width) \
40 return; \
41 if (y >= ps->height) \
42 return; \
43 if (x + w > ps->width) \
44 w = ps->width - x; \
45 if (y + h > ps->height) \
46 h = ps->height -y; \
47 } while(0)
48
49
50 /**
51 * Note: this is exactly like a8r8g8b8_get_tile() in sp_surface.c
52 * Share it someday.
53 */
54 static void
55 i915_get_tile_rgba(struct pipe_context *pipe,
56 struct pipe_surface *ps,
57 uint x, uint y, uint w, uint h, float *p)
58 {
59 const unsigned *src
60 = ((const unsigned *) (ps->region->map + ps->offset))
61 + y * ps->pitch + x;
62 unsigned i, j;
63 unsigned w0 = w;
64
65 CLIP_TILE;
66
67 switch (ps->format) {
68 case PIPE_FORMAT_U_A8_R8_G8_B8:
69 for (i = 0; i < h; i++) {
70 float *pRow = p;
71 for (j = 0; j < w; j++) {
72 const unsigned pixel = src[j];
73 pRow[0] = UBYTE_TO_FLOAT((pixel >> 16) & 0xff);
74 pRow[1] = UBYTE_TO_FLOAT((pixel >> 8) & 0xff);
75 pRow[2] = UBYTE_TO_FLOAT((pixel >> 0) & 0xff);
76 pRow[3] = UBYTE_TO_FLOAT((pixel >> 24) & 0xff);
77 pRow += 4;
78 }
79 src += ps->pitch;
80 p += w0 * 4;
81 }
82 break;
83 case PIPE_FORMAT_S8_Z24:
84 {
85 const float scale = 1.0f / (float) 0xffffff;
86 for (i = 0; i < h; i++) {
87 float *pRow = p;
88 for (j = 0; j < w; j++) {
89 const unsigned pixel = src[j];
90 pRow[0] =
91 pRow[1] =
92 pRow[2] =
93 pRow[3] = (pixel & 0xffffff) * scale;
94 pRow += 4;
95 }
96 src += ps->pitch;
97 p += w0 * 4;
98 }
99 }
100 break;
101 default:
102 assert(0);
103 }
104 }
105
106
107 static void
108 i915_put_tile_rgba(struct pipe_context *pipe,
109 struct pipe_surface *ps,
110 uint x, uint y, uint w, uint h, const float *p)
111 {
112 /* TODO */
113 assert(0);
114 }
115
116
117 /*
118 * XXX note: same as code in sp_surface.c
119 */
120 static void
121 i915_get_tile(struct pipe_context *pipe,
122 struct pipe_surface *ps,
123 uint x, uint y, uint w, uint h,
124 void *p, int dst_stride)
125 {
126 const uint cpp = ps->cpp;
127 const uint w0 = w;
128 const ubyte *pSrc;
129 ubyte *pDest;
130 uint i;
131
132 assert(ps->region->map);
133
134 CLIP_TILE;
135
136 if (dst_stride == 0) {
137 dst_stride = w0 * cpp;
138 }
139
140 pSrc = ps->region->map + ps->offset + (y * ps->pitch + x) * cpp;
141 pDest = (ubyte *) p;
142
143 for (i = 0; i < h; i++) {
144 memcpy(pDest, pSrc, w0 * cpp);
145 pDest += dst_stride;
146 pSrc += ps->pitch * cpp;
147 }
148 }
149
150
151 /*
152 * XXX note: same as code in sp_surface.c
153 */
154 static void
155 i915_put_tile(struct pipe_context *pipe,
156 struct pipe_surface *ps,
157 uint x, uint y, uint w, uint h,
158 const void *p, int src_stride)
159 {
160 const uint cpp = ps->cpp;
161 const uint w0 = w;
162 const ubyte *pSrc;
163 ubyte *pDest;
164 uint i;
165
166 assert(ps->region->map);
167
168 CLIP_TILE;
169
170 if (src_stride == 0) {
171 src_stride = w0 * cpp;
172 }
173
174 pSrc = (const ubyte *) p;
175 pDest = ps->region->map + ps->offset + (y * ps->pitch + x) * cpp;
176
177 for (i = 0; i < h; i++) {
178 memcpy(pDest, pSrc, w0 * cpp);
179 pDest += ps->pitch * cpp;
180 pSrc += src_stride;
181 }
182 }
183
184
185 /*
186 * XXX note: same as code in sp_surface.c
187 */
188 static struct pipe_surface *
189 i915_get_tex_surface(struct pipe_context *pipe,
190 struct pipe_texture *pt,
191 unsigned face, unsigned level, unsigned zslice)
192 {
193 struct i915_texture *tex = (struct i915_texture *)pt;
194 struct pipe_surface *ps;
195 unsigned offset; /* in bytes */
196
197 offset = tex->level_offset[level];
198
199 if (pt->target == PIPE_TEXTURE_CUBE) {
200 offset += tex->image_offset[level][face] * pt->cpp;
201 }
202 else if (pt->target == PIPE_TEXTURE_3D) {
203 offset += tex->image_offset[level][zslice] * pt->cpp;
204 }
205 else {
206 assert(face == 0);
207 assert(zslice == 0);
208 }
209
210 ps = pipe->winsys->surface_alloc(pipe->winsys, pt->format);
211 if (ps) {
212 assert(ps->format);
213 assert(ps->refcount);
214 pipe_region_reference(&ps->region, tex->region);
215 ps->cpp = pt->cpp;
216 ps->width = pt->width[level];
217 ps->height = pt->height[level];
218 ps->pitch = tex->pitch;
219 ps->offset = offset;
220 }
221 return ps;
222 }
223
224
225 /*
226 * XXX Move this into core Mesa?
227 */
228 static void
229 _mesa_copy_rect(ubyte * dst,
230 unsigned cpp,
231 unsigned dst_pitch,
232 unsigned dst_x,
233 unsigned dst_y,
234 unsigned width,
235 unsigned height,
236 const ubyte * src,
237 unsigned src_pitch,
238 unsigned src_x,
239 unsigned src_y)
240 {
241 unsigned i;
242
243 dst_pitch *= cpp;
244 src_pitch *= cpp;
245 dst += dst_x * cpp;
246 src += src_x * cpp;
247 dst += dst_y * dst_pitch;
248 src += src_y * dst_pitch;
249 width *= cpp;
250
251 if (width == dst_pitch && width == src_pitch)
252 memcpy(dst, src, height * width);
253 else {
254 for (i = 0; i < height; i++) {
255 memcpy(dst, src, width);
256 dst += dst_pitch;
257 src += src_pitch;
258 }
259 }
260 }
261
262
263 /* Upload data to a rectangular sub-region. Lots of choices how to do this:
264 *
265 * - memcpy by span to current destination
266 * - upload data as new buffer and blit
267 *
268 * Currently always memcpy.
269 */
270 static void
271 i915_surface_data(struct pipe_context *pipe,
272 struct pipe_surface *dst,
273 unsigned dstx, unsigned dsty,
274 const void *src, unsigned src_pitch,
275 unsigned srcx, unsigned srcy, unsigned width, unsigned height)
276 {
277 _mesa_copy_rect(pipe->region_map(pipe, dst->region) + dst->offset,
278 dst->cpp,
279 dst->pitch,
280 dstx, dsty, width, height, src, src_pitch, srcx, srcy);
281
282 pipe->region_unmap(pipe, dst->region);
283 }
284
285
286 /* Assumes all values are within bounds -- no checking at this level -
287 * do it higher up if required.
288 */
289 static void
290 i915_surface_copy(struct pipe_context *pipe,
291 struct pipe_surface *dst,
292 unsigned dstx, unsigned dsty,
293 struct pipe_surface *src,
294 unsigned srcx, unsigned srcy, unsigned width, unsigned height)
295 {
296 assert( dst != src );
297 assert( dst->cpp == src->cpp );
298
299 if (0) {
300 _mesa_copy_rect(pipe->region_map(pipe, dst->region) + dst->offset,
301 dst->cpp,
302 dst->pitch,
303 dstx, dsty,
304 width, height,
305 pipe->region_map(pipe, src->region) + src->offset,
306 src->pitch,
307 srcx, srcy);
308
309 pipe->region_unmap(pipe, src->region);
310 pipe->region_unmap(pipe, dst->region);
311 }
312 else {
313 i915_copy_blit( i915_context(pipe),
314 dst->cpp,
315 (short) src->pitch, src->region->buffer, src->offset,
316 (short) dst->pitch, dst->region->buffer, dst->offset,
317 (short) srcx, (short) srcy, (short) dstx, (short) dsty, (short) width, (short) height );
318 }
319 }
320
321 /* Fill a rectangular sub-region. Need better logic about when to
322 * push buffers into AGP - will currently do so whenever possible.
323 */
324 static ubyte *
325 get_pointer(struct pipe_surface *dst, unsigned x, unsigned y)
326 {
327 return dst->region->map + (y * dst->pitch + x) * dst->cpp;
328 }
329
330
331 static void
332 i915_surface_fill(struct pipe_context *pipe,
333 struct pipe_surface *dst,
334 unsigned dstx, unsigned dsty,
335 unsigned width, unsigned height, unsigned value)
336 {
337 if (0) {
338 unsigned i, j;
339
340 (void)pipe->region_map(pipe, dst->region);
341
342 switch (dst->cpp) {
343 case 1: {
344 ubyte *row = get_pointer(dst, dstx, dsty);
345 for (i = 0; i < height; i++) {
346 memset(row, value, width);
347 row += dst->pitch;
348 }
349 }
350 break;
351 case 2: {
352 ushort *row = (ushort *) get_pointer(dst, dstx, dsty);
353 for (i = 0; i < height; i++) {
354 for (j = 0; j < width; j++)
355 row[j] = (ushort) value;
356 row += dst->pitch;
357 }
358 }
359 break;
360 case 4: {
361 unsigned *row = (unsigned *) get_pointer(dst, dstx, dsty);
362 for (i = 0; i < height; i++) {
363 for (j = 0; j < width; j++)
364 row[j] = value;
365 row += dst->pitch;
366 }
367 }
368 break;
369 default:
370 assert(0);
371 break;
372 }
373 }
374 else {
375 i915_fill_blit( i915_context(pipe),
376 dst->cpp,
377 (short) dst->pitch,
378 dst->region->buffer, dst->offset,
379 (short) dstx, (short) dsty,
380 (short) width, (short) height,
381 value );
382 }
383 }
384
385
386 void
387 i915_init_surface_functions(struct i915_context *i915)
388 {
389 i915->pipe.get_tex_surface = i915_get_tex_surface;
390 i915->pipe.get_tile = i915_get_tile;
391 i915->pipe.put_tile = i915_put_tile;
392 i915->pipe.get_tile_rgba = i915_get_tile_rgba;
393 i915->pipe.put_tile_rgba = i915_put_tile_rgba;
394 i915->pipe.surface_data = i915_surface_data;
395 i915->pipe.surface_copy = i915_surface_copy;
396 i915->pipe.surface_fill = i915_surface_fill;
397 }