code for functional Z buffer surface
[mesa.git] / src / mesa / drivers / x11 / xm_surface.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.1
4 *
5 * Copyright (C) 1999-2007 Brian Paul 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 "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26 /**
27 * \file xm_surface.h
28 * Code to allow the softpipe code to write to X windows/buffers.
29 * This is a bit of a hack for now. We've basically got two different
30 * abstractions for color buffers: gl_renderbuffer and softpipe_surface.
31 * They'll need to get merged someday...
32 * For now, they're separate things that point to each other.
33 */
34
35
36 #include "glxheader.h"
37 #include "GL/xmesa.h"
38 #include "xmesaP.h"
39 #include "context.h"
40 #include "imports.h"
41 #include "macros.h"
42 #include "framebuffer.h"
43 #include "renderbuffer.h"
44
45 #include "pipe/p_state.h"
46 #include "pipe/softpipe/sp_context.h"
47 #include "pipe/softpipe/sp_surface.h"
48
49
50 /**
51 * An xm_surface is derived from a softpipe_surface
52 */
53 struct xmesa_surface
54 {
55 struct softpipe_surface sps;
56 struct xmesa_renderbuffer *xrb; /** ptr back to matching xmesa_renderbuffer */
57 struct gl_renderbuffer *rb; /* ptr to matching gl_renderbuffer */
58 };
59
60
61 /**
62 * Cast wrapper
63 */
64 static INLINE struct xmesa_surface *
65 xmesa_surface(struct softpipe_surface *sps)
66 {
67 return (struct xmesa_surface *) sps;
68 }
69
70
71 /**
72 * quad reading/writing
73 * These functions are just wrappers around the existing renderbuffer
74 * functions.
75 */
76
77 static void
78 read_quad_f(struct softpipe_surface *gs, GLint x, GLint y,
79 GLfloat (*rgba)[NUM_CHANNELS])
80 {
81 struct xmesa_surface *xmsurf = xmesa_surface(gs);
82 struct xmesa_renderbuffer *xrb = xmsurf->xrb;
83 GLubyte temp[16];
84 GLfloat *dst = (GLfloat *) rgba;
85 GLuint i;
86 GET_CURRENT_CONTEXT(ctx);
87 xrb->Base.GetRow(ctx, &xrb->Base, 2, x, y, temp);
88 xrb->Base.GetRow(ctx, &xrb->Base, 2, x, y + 1, temp + 8);
89 for (i = 0; i < 16; i++) {
90 dst[i] = UBYTE_TO_FLOAT(temp[i]);
91 }
92 }
93
94 static void
95 read_quad_f_swz(struct softpipe_surface *gs, GLint x, GLint y,
96 GLfloat (*rrrr)[QUAD_SIZE])
97 {
98 struct xmesa_surface *xmsurf = xmesa_surface(gs);
99 struct xmesa_renderbuffer *xrb = xmsurf->xrb;
100 GLubyte temp[16];
101 GLfloat *dst = (GLfloat *) rrrr;
102 GLuint i, j;
103 GET_CURRENT_CONTEXT(ctx);
104 xrb->Base.GetRow(ctx, &xrb->Base, 2, x, y, temp);
105 xrb->Base.GetRow(ctx, &xrb->Base, 2, x, y + 1, temp + 8);
106 for (i = 0; i < 4; i++) {
107 for (j = 0; j < 4; j++) {
108 dst[j * 4 + i] = UBYTE_TO_FLOAT(temp[i * 4 + j]);
109 }
110 }
111 }
112
113 static void
114 write_quad_f(struct softpipe_surface *gs, GLint x, GLint y,
115 GLfloat (*rgba)[NUM_CHANNELS])
116 {
117 struct xmesa_surface *xmsurf = xmesa_surface(gs);
118 struct xmesa_renderbuffer *xrb = xmsurf->xrb;
119 GLubyte temp[16];
120 const GLfloat *src = (const GLfloat *) rgba;
121 GLuint i;
122 GET_CURRENT_CONTEXT(ctx);
123 for (i = 0; i < 16; i++) {
124 temp[i] = FLOAT_TO_UBYTE(src[i]);
125 }
126 xrb->Base.PutRow(ctx, &xrb->Base, 2, x, y, temp, NULL);
127 xrb->Base.PutRow(ctx, &xrb->Base, 2, x, y + 1, temp + 8, NULL);
128 }
129
130 static void
131 write_quad_f_swz(struct softpipe_surface *gs, GLint x, GLint y,
132 GLfloat (*rrrr)[QUAD_SIZE])
133 {
134 struct xmesa_surface *xmsurf = xmesa_surface(gs);
135 struct xmesa_renderbuffer *xrb = xmsurf->xrb;
136 GLubyte temp[16];
137 const GLfloat *src = (const GLfloat *) rrrr;
138 GLuint i, j;
139 GET_CURRENT_CONTEXT(ctx);
140 for (i = 0; i < 4; i++) {
141 for (j = 0; j < 4; j++) {
142 temp[j * 4 + i] = FLOAT_TO_UBYTE(src[i * 4 + j]);
143 }
144 }
145 xrb->Base.PutRow(ctx, &xrb->Base, 2, x, y, temp, NULL);
146 xrb->Base.PutRow(ctx, &xrb->Base, 2, x, y + 1, temp + 8, NULL);
147 }
148
149 static void
150 read_quad_ub(struct softpipe_surface *gs, GLint x, GLint y,
151 GLubyte (*rgba)[NUM_CHANNELS])
152 {
153 struct xmesa_surface *xmsurf = xmesa_surface(gs);
154 struct xmesa_renderbuffer *xrb = xmsurf->xrb;
155 GET_CURRENT_CONTEXT(ctx);
156 xrb->Base.GetRow(ctx, &xrb->Base, 2, x, y, rgba);
157 xrb->Base.GetRow(ctx, &xrb->Base, 2, x, y + 1, rgba + 2);
158 }
159
160 static void
161 write_quad_ub(struct softpipe_surface *gs, GLint x, GLint y,
162 GLubyte (*rgba)[NUM_CHANNELS])
163 {
164 struct xmesa_surface *xmsurf = xmesa_surface(gs);
165 struct xmesa_renderbuffer *xrb = xmsurf->xrb;
166 GET_CURRENT_CONTEXT(ctx);
167 xrb->Base.GetRow(ctx, &xrb->Base, 2, x, y, rgba);
168 xrb->Base.GetRow(ctx, &xrb->Base, 2, x, y + 1, rgba + 2);
169 }
170
171 static void
172 write_mono_row_ub(struct softpipe_surface *gs, GLuint count, GLint x, GLint y,
173 GLubyte rgba[NUM_CHANNELS])
174 {
175 struct xmesa_surface *xmsurf = xmesa_surface(gs);
176 struct xmesa_renderbuffer *xrb = xmsurf->xrb;
177 GET_CURRENT_CONTEXT(ctx);
178 xrb->Base.PutMonoRow(ctx, &xrb->Base, count, x, y, rgba, NULL);
179 }
180
181
182 static struct xmesa_surface *
183 create_surface(XMesaContext xmctx, struct xmesa_renderbuffer *xrb)
184 {
185 struct xmesa_surface *xmsurf;
186
187 xmsurf = CALLOC_STRUCT(xmesa_surface);
188 if (xmsurf) {
189 xmsurf->xrb = xrb;
190 xmsurf->sps.surface.width = xrb->Base.Width;
191 xmsurf->sps.surface.height = xrb->Base.Height;
192
193 xmsurf->sps.read_quad_f = read_quad_f;
194 xmsurf->sps.read_quad_f_swz = read_quad_f_swz;
195 xmsurf->sps.read_quad_ub = read_quad_ub;
196 xmsurf->sps.write_quad_f = write_quad_f;
197 xmsurf->sps.write_quad_f_swz = write_quad_f_swz;
198 xmsurf->sps.write_quad_ub = write_quad_ub;
199 xmsurf->sps.write_mono_row_ub = write_mono_row_ub;
200
201 #if 0
202 if (xrb->ximage) {
203 xmsurf->sps.surface.ptr = (GLubyte *) xrb->ximage->data;
204 xmsurf->sps.surface.stride = xrb->ximage->bytes_per_line;
205 xmsurf->sps.surface.cpp = xrb->ximage->depth;
206
207 }
208 #endif
209 }
210 return xmsurf;
211 }
212
213
214 static void
215 free_surface(struct softpipe_surface *sps)
216 {
217 /* XXX may need to do more in the future */
218 free(sps);
219 }
220
221
222 /**
223 * Return generic surface pointer corresponding to the current color buffer.
224 */
225 struct pipe_surface *
226 xmesa_get_color_surface(GLcontext *ctx, GLuint buf)
227 {
228 XMesaContext xmctx = XMESA_CONTEXT(ctx);
229 struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0][buf];
230 struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb);
231 struct softpipe_surface *sps = (struct softpipe_surface *) xrb->pSurface;
232
233 if (!sps) {
234 xrb->pSurface = create_surface(xmctx, xrb);
235 }
236 else if (sps->surface.width != rb->Width ||
237 sps->surface.height != rb->Height) {
238 free_surface(sps);
239 xrb->pSurface = create_surface(xmctx, xrb);
240 }
241
242 return (struct pipe_surface *) xrb->pSurface;
243 }
244
245
246 static void
247 read_quad_z(struct softpipe_surface *sps,
248 GLint x, GLint y, GLfloat zzzz[QUAD_SIZE])
249 {
250 struct xmesa_surface *xmsurf = xmesa_surface(sps);
251 struct gl_renderbuffer *rb = xmsurf->rb;
252 GLushort temp[4];
253 GLuint i;
254 GET_CURRENT_CONTEXT(ctx);
255 rb->GetRow(ctx, rb, 2, x, y, temp);
256 rb->GetRow(ctx, rb, 2, x, y + 1, temp + 2);
257 for (i = 0; i < 4; i++) {
258 zzzz[i] = USHORT_TO_FLOAT(temp[i]);
259 }
260 }
261
262 static void
263 write_quad_z(struct softpipe_surface *sps,
264 GLint x, GLint y, const GLfloat zzzz[QUAD_SIZE])
265 {
266 struct xmesa_surface *xmsurf = xmesa_surface(sps);
267 struct gl_renderbuffer *rb = xmsurf->rb;
268 GLushort temp[4];
269 GLuint i;
270 GET_CURRENT_CONTEXT(ctx);
271 for (i = 0; i < 4; i++) {
272 CLAMPED_FLOAT_TO_USHORT(temp[i], zzzz[i]);
273 }
274 rb->PutRow(ctx, rb, 2, x, y, temp, NULL);
275 rb->PutRow(ctx, rb, 2, x, y + 1, temp + 2, NULL);
276 }
277
278
279 static struct xmesa_surface *
280 create_z_surface(XMesaContext xmctx, struct gl_renderbuffer *rb)
281 {
282 struct xmesa_surface *xmsurf;
283
284 xmsurf = CALLOC_STRUCT(xmesa_surface);
285 if (xmsurf) {
286 xmsurf->sps.surface.width = rb->Width;
287 xmsurf->sps.surface.height = rb->Height;
288 xmsurf->sps.read_quad_z = read_quad_z;
289 xmsurf->sps.write_quad_z = write_quad_z;
290 xmsurf->rb = rb;
291 }
292 return xmsurf;
293 }
294
295 /**
296 * Return a pipe_surface that wraps the current Z/depth buffer.
297 * XXX this is pretty much a total hack until gl_renderbuffers and
298 * pipe_surfaces are merged...
299 */
300 struct pipe_surface *
301 xmesa_get_z_surface(GLcontext *ctx)
302 {
303 XMesaContext xmctx = XMESA_CONTEXT(ctx);
304 struct gl_renderbuffer *rb = ctx->DrawBuffer->_DepthBuffer;
305 static struct xmesa_surface *xms = NULL;
306
307 if (!rb)
308 return NULL;
309
310 if (!xms) {
311 xms = create_z_surface(xmctx, rb);
312 }
313 else if (xms->sps.surface.width != rb->Width ||
314 xms->sps.surface.height != rb->Height) {
315 free_surface(&xms->sps);
316 xms = create_z_surface(xmctx, rb);
317 }
318
319 return (struct pipe_surface *) &xms->sps.surface;
320 }
321
322
323 struct pipe_surface *
324 xmesa_get_stencil_surface(GLcontext *ctx)
325 {
326 return NULL;
327 }
328