Rev 4358 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4358 | Serge | 1 | /* |
2 | * Copyright 2008, 2010 George Sapountzis |
||
3 | * |
||
4 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
5 | * copy of this software and associated documentation files (the "Software"), |
||
6 | * to deal in the Software without restriction, including without limitation |
||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||
8 | * and/or sell copies of the Software, and to permit persons to whom the |
||
9 | * Software is furnished to do so, subject to the following conditions: |
||
10 | * |
||
11 | * The above copyright notice and this permission notice shall be included |
||
12 | * in all copies or substantial portions of the Software. |
||
13 | * |
||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
||
15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||
17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR |
||
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
||
20 | * OTHER DEALINGS IN THE SOFTWARE. |
||
21 | */ |
||
22 | |||
23 | /* |
||
24 | * DRI software rasterizer |
||
25 | * |
||
26 | * This is the mesa swrast module packaged into a DRI driver structure. |
||
27 | * |
||
28 | * The front-buffer is allocated by the loader. The loader provides read/write |
||
29 | * callbacks for access to the front-buffer. The driver uses a scratch row for |
||
30 | * front-buffer rendering to avoid repeated calls to the loader. |
||
31 | * |
||
32 | * The back-buffer is allocated by the driver and is private. |
||
33 | */ |
||
34 | |||
35 | #include "main/api_exec.h" |
||
36 | #include "main/context.h" |
||
37 | #include "main/extensions.h" |
||
38 | #include "main/formats.h" |
||
39 | #include "main/framebuffer.h" |
||
40 | #include "main/imports.h" |
||
41 | #include "main/renderbuffer.h" |
||
42 | #include "main/version.h" |
||
43 | #include "main/vtxfmt.h" |
||
44 | #include "swrast/swrast.h" |
||
45 | #include "swrast/s_renderbuffer.h" |
||
46 | #include "swrast_setup/swrast_setup.h" |
||
47 | #include "tnl/tnl.h" |
||
48 | #include "tnl/t_context.h" |
||
49 | #include "tnl/t_pipeline.h" |
||
50 | #include "vbo/vbo.h" |
||
51 | #include "drivers/common/driverfuncs.h" |
||
52 | #include "drivers/common/meta.h" |
||
53 | #include "utils.h" |
||
54 | |||
55 | #include "main/teximage.h" |
||
56 | #include "main/texformat.h" |
||
57 | #include "main/texstate.h" |
||
58 | |||
59 | #include "swrast_priv.h" |
||
60 | #include "swrast/s_context.h" |
||
61 | |||
62 | |||
63 | /** |
||
64 | * Screen and config-related functions |
||
65 | */ |
||
66 | |||
67 | static void swrastSetTexBuffer2(__DRIcontext *pDRICtx, GLint target, |
||
68 | GLint texture_format, __DRIdrawable *dPriv) |
||
69 | { |
||
70 | struct dri_context *dri_ctx; |
||
71 | int x, y, w, h; |
||
72 | __DRIscreen *sPriv = dPriv->driScreenPriv; |
||
73 | struct gl_texture_unit *texUnit; |
||
74 | struct gl_texture_object *texObj; |
||
75 | struct gl_texture_image *texImage; |
||
76 | struct swrast_texture_image *swImage; |
||
77 | uint32_t internalFormat; |
||
78 | gl_format texFormat; |
||
79 | |||
80 | dri_ctx = pDRICtx->driverPrivate; |
||
81 | |||
82 | internalFormat = (texture_format == __DRI_TEXTURE_FORMAT_RGB ? 3 : 4); |
||
83 | |||
84 | texUnit = _mesa_get_current_tex_unit(&dri_ctx->Base); |
||
85 | texObj = _mesa_select_tex_object(&dri_ctx->Base, texUnit, target); |
||
86 | texImage = _mesa_get_tex_image(&dri_ctx->Base, texObj, target, 0); |
||
87 | swImage = swrast_texture_image(texImage); |
||
88 | |||
89 | _mesa_lock_texture(&dri_ctx->Base, texObj); |
||
90 | |||
91 | sPriv->swrast_loader->getDrawableInfo(dPriv, &x, &y, &w, &h, dPriv->loaderPrivate); |
||
92 | |||
93 | if (texture_format == __DRI_TEXTURE_FORMAT_RGB) |
||
94 | texFormat = MESA_FORMAT_XRGB8888; |
||
95 | else |
||
96 | texFormat = MESA_FORMAT_ARGB8888; |
||
97 | |||
98 | _mesa_init_teximage_fields(&dri_ctx->Base, texImage, |
||
99 | w, h, 1, 0, internalFormat, texFormat); |
||
100 | |||
101 | sPriv->swrast_loader->getImage(dPriv, x, y, w, h, (char *)swImage->Buffer, |
||
102 | dPriv->loaderPrivate); |
||
103 | |||
104 | _mesa_unlock_texture(&dri_ctx->Base, texObj); |
||
105 | } |
||
106 | |||
107 | static void swrastSetTexBuffer(__DRIcontext *pDRICtx, GLint target, |
||
108 | __DRIdrawable *dPriv) |
||
109 | { |
||
110 | swrastSetTexBuffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv); |
||
111 | } |
||
112 | |||
113 | static const __DRItexBufferExtension swrastTexBufferExtension = { |
||
114 | { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION }, |
||
115 | swrastSetTexBuffer, |
||
116 | swrastSetTexBuffer2, |
||
117 | }; |
||
118 | |||
119 | static const __DRIextension *dri_screen_extensions[] = { |
||
120 | &swrastTexBufferExtension.base, |
||
121 | NULL |
||
122 | }; |
||
123 | |||
124 | static __DRIconfig ** |
||
125 | swrastFillInModes(__DRIscreen *psp, |
||
126 | unsigned pixel_bits, unsigned depth_bits, |
||
127 | unsigned stencil_bits, GLboolean have_back_buffer) |
||
128 | { |
||
129 | __DRIconfig **configs; |
||
130 | unsigned depth_buffer_factor; |
||
131 | unsigned back_buffer_factor; |
||
132 | gl_format format; |
||
133 | |||
134 | /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't |
||
135 | * support pageflipping at all. |
||
136 | */ |
||
137 | static const GLenum back_buffer_modes[] = { |
||
138 | GLX_NONE, GLX_SWAP_UNDEFINED_OML |
||
139 | }; |
||
140 | |||
141 | uint8_t depth_bits_array[4]; |
||
142 | uint8_t stencil_bits_array[4]; |
||
143 | uint8_t msaa_samples_array[1]; |
||
144 | |||
145 | (void) psp; |
||
146 | (void) have_back_buffer; |
||
147 | |||
148 | depth_bits_array[0] = 0; |
||
149 | depth_bits_array[1] = 0; |
||
150 | depth_bits_array[2] = depth_bits; |
||
151 | depth_bits_array[3] = depth_bits; |
||
152 | |||
153 | /* Just like with the accumulation buffer, always provide some modes |
||
154 | * with a stencil buffer. |
||
155 | */ |
||
156 | stencil_bits_array[0] = 0; |
||
157 | stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits; |
||
158 | stencil_bits_array[2] = 0; |
||
159 | stencil_bits_array[3] = (stencil_bits == 0) ? 8 : stencil_bits; |
||
160 | |||
161 | msaa_samples_array[0] = 0; |
||
162 | |||
163 | depth_buffer_factor = 4; |
||
164 | back_buffer_factor = 2; |
||
165 | |||
166 | switch (pixel_bits) { |
||
167 | case 16: |
||
168 | format = MESA_FORMAT_RGB565; |
||
169 | break; |
||
170 | case 24: |
||
171 | format = MESA_FORMAT_XRGB8888; |
||
172 | break; |
||
173 | case 32: |
||
174 | format = MESA_FORMAT_ARGB8888; |
||
175 | break; |
||
176 | default: |
||
177 | fprintf(stderr, "[%s:%u] bad depth %d\n", __func__, __LINE__, |
||
178 | pixel_bits); |
||
179 | return NULL; |
||
180 | } |
||
181 | |||
182 | configs = driCreateConfigs(format, |
||
183 | depth_bits_array, stencil_bits_array, |
||
184 | depth_buffer_factor, back_buffer_modes, |
||
185 | back_buffer_factor, msaa_samples_array, 1, |
||
186 | GL_TRUE); |
||
187 | if (configs == NULL) { |
||
188 | fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__, |
||
189 | __LINE__); |
||
190 | return NULL; |
||
191 | } |
||
192 | |||
193 | return configs; |
||
194 | } |
||
195 | |||
196 | static const __DRIconfig ** |
||
197 | dri_init_screen(__DRIscreen * psp) |
||
198 | { |
||
199 | __DRIconfig **configs16, **configs24, **configs32; |
||
200 | |||
201 | TRACE; |
||
202 | |||
203 | psp->extensions = dri_screen_extensions; |
||
204 | |||
205 | configs16 = swrastFillInModes(psp, 16, 16, 0, 1); |
||
206 | configs24 = swrastFillInModes(psp, 24, 24, 8, 1); |
||
207 | configs32 = swrastFillInModes(psp, 32, 24, 8, 1); |
||
208 | |||
209 | configs24 = driConcatConfigs(configs16, configs24); |
||
210 | configs32 = driConcatConfigs(configs24, configs32); |
||
211 | |||
212 | return (const __DRIconfig **)configs32; |
||
213 | } |
||
214 | |||
215 | static void |
||
216 | dri_destroy_screen(__DRIscreen * sPriv) |
||
217 | { |
||
218 | TRACE; |
||
219 | (void) sPriv; |
||
220 | } |
||
221 | |||
222 | |||
223 | /** |
||
224 | * Framebuffer and renderbuffer-related functions. |
||
225 | */ |
||
226 | |||
227 | static GLuint |
||
228 | choose_pixel_format(const struct gl_config *v) |
||
229 | { |
||
230 | int depth = v->rgbBits; |
||
231 | |||
232 | if (depth == 32 |
||
233 | && v->redMask == 0xff0000 |
||
234 | && v->greenMask == 0x00ff00 |
||
235 | && v->blueMask == 0x0000ff) |
||
236 | return PF_A8R8G8B8; |
||
237 | else if (depth == 24 |
||
238 | && v->redMask == 0xff0000 |
||
239 | && v->greenMask == 0x00ff00 |
||
240 | && v->blueMask == 0x0000ff) |
||
241 | return PF_X8R8G8B8; |
||
242 | else if (depth == 16 |
||
243 | && v->redMask == 0xf800 |
||
244 | && v->greenMask == 0x07e0 |
||
245 | && v->blueMask == 0x001f) |
||
246 | return PF_R5G6B5; |
||
247 | else if (depth == 8 |
||
248 | && v->redMask == 0x07 |
||
249 | && v->greenMask == 0x38 |
||
250 | && v->blueMask == 0xc0) |
||
251 | return PF_R3G3B2; |
||
252 | |||
253 | _mesa_problem( NULL, "unexpected format in %s", __FUNCTION__ ); |
||
254 | return 0; |
||
255 | } |
||
256 | |||
257 | static void |
||
258 | swrast_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb) |
||
259 | { |
||
260 | struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb); |
||
261 | |||
262 | TRACE; |
||
263 | |||
264 | free(xrb->Base.Buffer); |
||
265 | _mesa_delete_renderbuffer(ctx, rb); |
||
266 | } |
||
267 | |||
268 | /* see bytes_per_line in libGL */ |
||
269 | static INLINE int |
||
270 | bytes_per_line(unsigned pitch_bits, unsigned mul) |
||
271 | { |
||
272 | unsigned mask = mul - 1; |
||
273 | |||
274 | return ((pitch_bits + mask) & ~mask) / 8; |
||
275 | } |
||
276 | |||
277 | static GLboolean |
||
278 | swrast_alloc_front_storage(struct gl_context *ctx, struct gl_renderbuffer *rb, |
||
279 | GLenum internalFormat, GLuint width, GLuint height) |
||
280 | { |
||
281 | struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb); |
||
282 | |||
283 | TRACE; |
||
284 | |||
285 | (void) ctx; |
||
286 | (void) internalFormat; |
||
287 | |||
288 | xrb->Base.Buffer = NULL; |
||
289 | rb->Width = width; |
||
290 | rb->Height = height; |
||
291 | xrb->pitch = bytes_per_line(width * xrb->bpp, 32); |
||
292 | |||
293 | return GL_TRUE; |
||
294 | } |
||
295 | |||
296 | static GLboolean |
||
297 | swrast_alloc_back_storage(struct gl_context *ctx, struct gl_renderbuffer *rb, |
||
298 | GLenum internalFormat, GLuint width, GLuint height) |
||
299 | { |
||
300 | struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb); |
||
301 | |||
302 | TRACE; |
||
303 | |||
304 | free(xrb->Base.Buffer); |
||
305 | |||
306 | swrast_alloc_front_storage(ctx, rb, internalFormat, width, height); |
||
307 | |||
308 | xrb->Base.Buffer = malloc(height * xrb->pitch); |
||
309 | |||
310 | return GL_TRUE; |
||
311 | } |
||
312 | |||
313 | static struct dri_swrast_renderbuffer * |
||
314 | swrast_new_renderbuffer(const struct gl_config *visual, __DRIdrawable *dPriv, |
||
315 | GLboolean front) |
||
316 | { |
||
317 | struct dri_swrast_renderbuffer *xrb = calloc(1, sizeof *xrb); |
||
318 | struct gl_renderbuffer *rb; |
||
319 | GLuint pixel_format; |
||
320 | |||
321 | TRACE; |
||
322 | |||
323 | if (!xrb) |
||
324 | return NULL; |
||
325 | |||
326 | rb = &xrb->Base.Base; |
||
327 | |||
328 | _mesa_init_renderbuffer(rb, 0); |
||
329 | |||
330 | pixel_format = choose_pixel_format(visual); |
||
331 | |||
332 | xrb->dPriv = dPriv; |
||
333 | xrb->Base.Base.Delete = swrast_delete_renderbuffer; |
||
334 | if (front) { |
||
335 | rb->AllocStorage = swrast_alloc_front_storage; |
||
336 | } |
||
337 | else { |
||
338 | rb->AllocStorage = swrast_alloc_back_storage; |
||
339 | } |
||
340 | |||
341 | switch (pixel_format) { |
||
342 | case PF_A8R8G8B8: |
||
343 | rb->Format = MESA_FORMAT_ARGB8888; |
||
344 | rb->InternalFormat = GL_RGBA; |
||
345 | rb->_BaseFormat = GL_RGBA; |
||
346 | xrb->bpp = 32; |
||
347 | break; |
||
348 | case PF_X8R8G8B8: |
||
349 | rb->Format = MESA_FORMAT_ARGB8888; /* XXX */ |
||
350 | rb->InternalFormat = GL_RGB; |
||
351 | rb->_BaseFormat = GL_RGB; |
||
352 | xrb->bpp = 32; |
||
353 | break; |
||
354 | case PF_R5G6B5: |
||
355 | rb->Format = MESA_FORMAT_RGB565; |
||
356 | rb->InternalFormat = GL_RGB; |
||
357 | rb->_BaseFormat = GL_RGB; |
||
358 | xrb->bpp = 16; |
||
359 | break; |
||
360 | case PF_R3G3B2: |
||
361 | rb->Format = MESA_FORMAT_RGB332; |
||
362 | rb->InternalFormat = GL_RGB; |
||
363 | rb->_BaseFormat = GL_RGB; |
||
364 | xrb->bpp = 8; |
||
365 | break; |
||
366 | default: |
||
367 | free(xrb); |
||
368 | return NULL; |
||
369 | } |
||
370 | |||
371 | return xrb; |
||
372 | } |
||
373 | |||
374 | static void |
||
375 | swrast_map_renderbuffer(struct gl_context *ctx, |
||
376 | struct gl_renderbuffer *rb, |
||
377 | GLuint x, GLuint y, GLuint w, GLuint h, |
||
378 | GLbitfield mode, |
||
379 | GLubyte **out_map, |
||
380 | GLint *out_stride) |
||
381 | { |
||
382 | struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb); |
||
383 | GLubyte *map = xrb->Base.Buffer; |
||
384 | int cpp = _mesa_get_format_bytes(rb->Format); |
||
385 | int stride = rb->Width * cpp; |
||
386 | |||
387 | if (rb->AllocStorage == swrast_alloc_front_storage) { |
||
388 | __DRIdrawable *dPriv = xrb->dPriv; |
||
389 | __DRIscreen *sPriv = dPriv->driScreenPriv; |
||
390 | |||
391 | xrb->map_mode = mode; |
||
392 | xrb->map_x = x; |
||
393 | xrb->map_y = y; |
||
394 | xrb->map_w = w; |
||
395 | xrb->map_h = h; |
||
396 | |||
397 | stride = w * cpp; |
||
398 | xrb->Base.Buffer = malloc(h * stride); |
||
399 | |||
4401 | Serge | 400 | sPriv->swrast_loader->getImage(dPriv, x, rb->Height - y - h, w, h, |
4358 | Serge | 401 | (char *) xrb->Base.Buffer, |
402 | dPriv->loaderPrivate); |
||
403 | |||
4401 | Serge | 404 | *out_map = xrb->Base.Buffer + (h - 1) * stride; |
405 | *out_stride = -stride; |
||
4358 | Serge | 406 | return; |
407 | } |
||
408 | |||
409 | ASSERT(xrb->Base.Buffer); |
||
410 | |||
411 | if (rb->AllocStorage == swrast_alloc_back_storage) { |
||
412 | map += (rb->Height - 1) * stride; |
||
413 | stride = -stride; |
||
414 | } |
||
415 | |||
416 | map += (GLsizei)y * stride; |
||
417 | map += (GLsizei)x * cpp; |
||
418 | |||
419 | *out_map = map; |
||
420 | *out_stride = stride; |
||
421 | } |
||
422 | |||
423 | static void |
||
424 | swrast_unmap_renderbuffer(struct gl_context *ctx, |
||
425 | struct gl_renderbuffer *rb) |
||
426 | { |
||
427 | struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb); |
||
428 | |||
429 | if (rb->AllocStorage == swrast_alloc_front_storage) { |
||
430 | __DRIdrawable *dPriv = xrb->dPriv; |
||
431 | __DRIscreen *sPriv = dPriv->driScreenPriv; |
||
432 | |||
433 | if (xrb->map_mode & GL_MAP_WRITE_BIT) { |
||
434 | sPriv->swrast_loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_DRAW, |
||
435 | xrb->map_x, xrb->map_y, |
||
436 | xrb->map_w, xrb->map_h, |
||
437 | (char *) xrb->Base.Buffer, |
||
438 | dPriv->loaderPrivate); |
||
439 | } |
||
440 | |||
441 | free(xrb->Base.Buffer); |
||
442 | xrb->Base.Buffer = NULL; |
||
443 | } |
||
444 | } |
||
445 | |||
446 | static GLboolean |
||
447 | dri_create_buffer(__DRIscreen * sPriv, |
||
448 | __DRIdrawable * dPriv, |
||
449 | const struct gl_config * visual, GLboolean isPixmap) |
||
450 | { |
||
451 | struct dri_drawable *drawable = NULL; |
||
452 | struct gl_framebuffer *fb; |
||
453 | struct dri_swrast_renderbuffer *frontrb, *backrb; |
||
454 | |||
455 | TRACE; |
||
456 | |||
457 | (void) sPriv; |
||
458 | (void) isPixmap; |
||
459 | |||
460 | drawable = CALLOC_STRUCT(dri_drawable); |
||
461 | if (drawable == NULL) |
||
462 | goto drawable_fail; |
||
463 | |||
464 | dPriv->driverPrivate = drawable; |
||
465 | drawable->dPriv = dPriv; |
||
466 | |||
467 | drawable->row = malloc(SWRAST_MAX_WIDTH * 4); |
||
468 | if (drawable->row == NULL) |
||
469 | goto drawable_fail; |
||
470 | |||
471 | fb = &drawable->Base; |
||
472 | |||
473 | /* basic framebuffer setup */ |
||
474 | _mesa_initialize_window_framebuffer(fb, visual); |
||
475 | |||
476 | /* add front renderbuffer */ |
||
477 | frontrb = swrast_new_renderbuffer(visual, dPriv, GL_TRUE); |
||
478 | _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontrb->Base.Base); |
||
479 | |||
480 | /* add back renderbuffer */ |
||
481 | if (visual->doubleBufferMode) { |
||
482 | backrb = swrast_new_renderbuffer(visual, dPriv, GL_FALSE); |
||
483 | _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backrb->Base.Base); |
||
484 | } |
||
485 | |||
486 | /* add software renderbuffers */ |
||
487 | _swrast_add_soft_renderbuffers(fb, |
||
488 | GL_FALSE, /* color */ |
||
489 | visual->haveDepthBuffer, |
||
490 | visual->haveStencilBuffer, |
||
491 | visual->haveAccumBuffer, |
||
492 | GL_FALSE, /* alpha */ |
||
493 | GL_FALSE /* aux bufs */); |
||
494 | |||
495 | return GL_TRUE; |
||
496 | |||
497 | drawable_fail: |
||
498 | |||
499 | if (drawable) |
||
500 | free(drawable->row); |
||
501 | |||
502 | free(drawable); |
||
503 | |||
504 | return GL_FALSE; |
||
505 | } |
||
506 | |||
507 | static void |
||
508 | dri_destroy_buffer(__DRIdrawable * dPriv) |
||
509 | { |
||
510 | TRACE; |
||
511 | |||
512 | if (dPriv) { |
||
513 | struct dri_drawable *drawable = dri_drawable(dPriv); |
||
514 | struct gl_framebuffer *fb; |
||
515 | |||
516 | free(drawable->row); |
||
517 | |||
518 | fb = &drawable->Base; |
||
519 | |||
520 | fb->DeletePending = GL_TRUE; |
||
521 | _mesa_reference_framebuffer(&fb, NULL); |
||
522 | } |
||
523 | } |
||
524 | |||
525 | static void |
||
526 | dri_swap_buffers(__DRIdrawable * dPriv) |
||
527 | { |
||
528 | __DRIscreen *sPriv = dPriv->driScreenPriv; |
||
529 | |||
530 | GET_CURRENT_CONTEXT(ctx); |
||
531 | |||
532 | struct dri_drawable *drawable = dri_drawable(dPriv); |
||
533 | struct gl_framebuffer *fb; |
||
534 | struct dri_swrast_renderbuffer *frontrb, *backrb; |
||
535 | |||
536 | TRACE; |
||
537 | |||
538 | fb = &drawable->Base; |
||
539 | |||
540 | frontrb = |
||
541 | dri_swrast_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer); |
||
542 | backrb = |
||
543 | dri_swrast_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer); |
||
544 | |||
545 | /* check for signle-buffered */ |
||
546 | if (backrb == NULL) |
||
547 | return; |
||
548 | |||
549 | /* check if swapping currently bound buffer */ |
||
550 | if (ctx && ctx->DrawBuffer == fb) { |
||
551 | /* flush pending rendering */ |
||
552 | _mesa_notifySwapBuffers(ctx); |
||
553 | } |
||
554 | |||
555 | sPriv->swrast_loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP, |
||
556 | 0, 0, |
||
557 | frontrb->Base.Base.Width, |
||
558 | frontrb->Base.Base.Height, |
||
559 | (char *) backrb->Base.Buffer, |
||
560 | dPriv->loaderPrivate); |
||
561 | } |
||
562 | |||
563 | |||
564 | /** |
||
565 | * General device driver functions. |
||
566 | */ |
||
567 | |||
568 | static void |
||
569 | get_window_size( struct gl_framebuffer *fb, GLsizei *w, GLsizei *h ) |
||
570 | { |
||
571 | __DRIdrawable *dPriv = swrast_drawable(fb)->dPriv; |
||
572 | __DRIscreen *sPriv = dPriv->driScreenPriv; |
||
573 | int x, y; |
||
574 | |||
575 | sPriv->swrast_loader->getDrawableInfo(dPriv, |
||
576 | &x, &y, w, h, |
||
577 | dPriv->loaderPrivate); |
||
578 | } |
||
579 | |||
580 | static void |
||
581 | swrast_check_and_update_window_size( struct gl_context *ctx, struct gl_framebuffer *fb ) |
||
582 | { |
||
583 | GLsizei width, height; |
||
584 | |||
585 | get_window_size(fb, &width, &height); |
||
586 | if (fb->Width != width || fb->Height != height) { |
||
587 | _mesa_resize_framebuffer(ctx, fb, width, height); |
||
588 | } |
||
589 | } |
||
590 | |||
591 | static const GLubyte * |
||
592 | get_string(struct gl_context *ctx, GLenum pname) |
||
593 | { |
||
594 | (void) ctx; |
||
595 | switch (pname) { |
||
596 | case GL_VENDOR: |
||
597 | return (const GLubyte *) "Mesa Project"; |
||
598 | case GL_RENDERER: |
||
599 | return (const GLubyte *) "Software Rasterizer"; |
||
600 | default: |
||
601 | return NULL; |
||
602 | } |
||
603 | } |
||
604 | |||
605 | static void |
||
606 | update_state( struct gl_context *ctx, GLuint new_state ) |
||
607 | { |
||
608 | /* not much to do here - pass it on */ |
||
609 | _swrast_InvalidateState( ctx, new_state ); |
||
610 | _swsetup_InvalidateState( ctx, new_state ); |
||
611 | _vbo_InvalidateState( ctx, new_state ); |
||
612 | _tnl_InvalidateState( ctx, new_state ); |
||
613 | } |
||
614 | |||
615 | static void |
||
616 | viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h) |
||
617 | { |
||
618 | struct gl_framebuffer *draw = ctx->WinSysDrawBuffer; |
||
619 | struct gl_framebuffer *read = ctx->WinSysReadBuffer; |
||
620 | |||
621 | (void) x; |
||
622 | (void) y; |
||
623 | (void) w; |
||
624 | (void) h; |
||
625 | swrast_check_and_update_window_size(ctx, draw); |
||
626 | swrast_check_and_update_window_size(ctx, read); |
||
627 | } |
||
628 | |||
629 | static gl_format swrastChooseTextureFormat(struct gl_context * ctx, |
||
630 | GLenum target, |
||
631 | GLint internalFormat, |
||
632 | GLenum format, |
||
633 | GLenum type) |
||
634 | { |
||
635 | if (internalFormat == GL_RGB) |
||
636 | return MESA_FORMAT_XRGB8888; |
||
637 | return _mesa_choose_tex_format(ctx, target, internalFormat, format, type); |
||
638 | } |
||
639 | |||
640 | static void |
||
641 | swrast_init_driver_functions(struct dd_function_table *driver) |
||
642 | { |
||
643 | driver->GetString = get_string; |
||
644 | driver->UpdateState = update_state; |
||
645 | driver->Viewport = viewport; |
||
646 | driver->ChooseTextureFormat = swrastChooseTextureFormat; |
||
647 | driver->MapRenderbuffer = swrast_map_renderbuffer; |
||
648 | driver->UnmapRenderbuffer = swrast_unmap_renderbuffer; |
||
649 | } |
||
650 | |||
651 | /** |
||
652 | * Context-related functions. |
||
653 | */ |
||
654 | |||
655 | static GLboolean |
||
656 | dri_create_context(gl_api api, |
||
657 | const struct gl_config * visual, |
||
658 | __DRIcontext * cPriv, |
||
659 | unsigned major_version, |
||
660 | unsigned minor_version, |
||
661 | uint32_t flags, |
||
662 | unsigned *error, |
||
663 | void *sharedContextPrivate) |
||
664 | { |
||
665 | struct dri_context *ctx = NULL; |
||
666 | struct dri_context *share = (struct dri_context *)sharedContextPrivate; |
||
667 | struct gl_context *mesaCtx = NULL; |
||
668 | struct gl_context *sharedCtx = NULL; |
||
669 | struct dd_function_table functions; |
||
670 | |||
671 | TRACE; |
||
672 | |||
673 | /* Flag filtering is handled in dri2CreateContextAttribs. |
||
674 | */ |
||
675 | (void) flags; |
||
676 | |||
677 | switch (api) { |
||
678 | case API_OPENGL_COMPAT: |
||
679 | if (major_version > 2 |
||
680 | || (major_version == 2 && minor_version > 1)) { |
||
681 | *error = __DRI_CTX_ERROR_BAD_VERSION; |
||
682 | return GL_FALSE; |
||
683 | } |
||
684 | break; |
||
685 | case API_OPENGLES: |
||
686 | case API_OPENGLES2: |
||
687 | break; |
||
688 | case API_OPENGL_CORE: |
||
689 | *error = __DRI_CTX_ERROR_BAD_API; |
||
690 | return GL_FALSE; |
||
691 | } |
||
692 | |||
693 | ctx = CALLOC_STRUCT(dri_context); |
||
694 | if (ctx == NULL) { |
||
695 | *error = __DRI_CTX_ERROR_NO_MEMORY; |
||
696 | goto context_fail; |
||
697 | } |
||
698 | |||
699 | cPriv->driverPrivate = ctx; |
||
700 | ctx->cPriv = cPriv; |
||
701 | |||
702 | /* build table of device driver functions */ |
||
703 | _mesa_init_driver_functions(&functions); |
||
704 | swrast_init_driver_functions(&functions); |
||
705 | |||
706 | if (share) { |
||
707 | sharedCtx = &share->Base; |
||
708 | } |
||
709 | |||
710 | mesaCtx = &ctx->Base; |
||
711 | |||
712 | /* basic context setup */ |
||
713 | if (!_mesa_initialize_context(mesaCtx, api, visual, sharedCtx, &functions)) { |
||
714 | *error = __DRI_CTX_ERROR_NO_MEMORY; |
||
715 | goto context_fail; |
||
716 | } |
||
717 | |||
718 | /* do bounds checking to prevent segfaults and server crashes! */ |
||
719 | mesaCtx->Const.CheckArrayBounds = GL_TRUE; |
||
720 | |||
721 | /* create module contexts */ |
||
722 | _swrast_CreateContext( mesaCtx ); |
||
723 | _vbo_CreateContext( mesaCtx ); |
||
724 | _tnl_CreateContext( mesaCtx ); |
||
725 | _swsetup_CreateContext( mesaCtx ); |
||
726 | _swsetup_Wakeup( mesaCtx ); |
||
727 | |||
728 | /* use default TCL pipeline */ |
||
729 | { |
||
730 | TNLcontext *tnl = TNL_CONTEXT(mesaCtx); |
||
731 | tnl->Driver.RunPipeline = _tnl_run_pipeline; |
||
732 | } |
||
733 | |||
734 | _mesa_meta_init(mesaCtx); |
||
735 | _mesa_enable_sw_extensions(mesaCtx); |
||
736 | |||
737 | _mesa_compute_version(mesaCtx); |
||
738 | |||
739 | _mesa_initialize_dispatch_tables(mesaCtx); |
||
740 | _mesa_initialize_vbo_vtxfmt(mesaCtx); |
||
741 | |||
742 | *error = __DRI_CTX_ERROR_SUCCESS; |
||
743 | return GL_TRUE; |
||
744 | |||
745 | context_fail: |
||
746 | |||
747 | free(ctx); |
||
748 | |||
749 | return GL_FALSE; |
||
750 | } |
||
751 | |||
752 | static void |
||
753 | dri_destroy_context(__DRIcontext * cPriv) |
||
754 | { |
||
755 | TRACE; |
||
756 | |||
757 | if (cPriv) { |
||
758 | struct dri_context *ctx = dri_context(cPriv); |
||
759 | struct gl_context *mesaCtx; |
||
760 | |||
761 | mesaCtx = &ctx->Base; |
||
762 | |||
763 | _mesa_meta_free(mesaCtx); |
||
764 | _swsetup_DestroyContext( mesaCtx ); |
||
765 | _swrast_DestroyContext( mesaCtx ); |
||
766 | _tnl_DestroyContext( mesaCtx ); |
||
767 | _vbo_DestroyContext( mesaCtx ); |
||
768 | _mesa_destroy_context( mesaCtx ); |
||
769 | } |
||
770 | } |
||
771 | |||
772 | static GLboolean |
||
773 | dri_make_current(__DRIcontext * cPriv, |
||
774 | __DRIdrawable * driDrawPriv, |
||
775 | __DRIdrawable * driReadPriv) |
||
776 | { |
||
777 | struct gl_context *mesaCtx; |
||
778 | struct gl_framebuffer *mesaDraw; |
||
779 | struct gl_framebuffer *mesaRead; |
||
780 | TRACE; |
||
781 | |||
782 | if (cPriv) { |
||
783 | struct dri_context *ctx = dri_context(cPriv); |
||
784 | struct dri_drawable *draw; |
||
785 | struct dri_drawable *read; |
||
786 | |||
787 | if (!driDrawPriv || !driReadPriv) |
||
788 | return GL_FALSE; |
||
789 | |||
790 | draw = dri_drawable(driDrawPriv); |
||
791 | read = dri_drawable(driReadPriv); |
||
792 | mesaCtx = &ctx->Base; |
||
793 | mesaDraw = &draw->Base; |
||
794 | mesaRead = &read->Base; |
||
795 | |||
796 | /* check for same context and buffer */ |
||
797 | if (mesaCtx == _mesa_get_current_context() |
||
798 | && mesaCtx->DrawBuffer == mesaDraw |
||
799 | && mesaCtx->ReadBuffer == mesaRead) { |
||
800 | return GL_TRUE; |
||
801 | } |
||
802 | |||
803 | _glapi_check_multithread(); |
||
804 | |||
805 | swrast_check_and_update_window_size(mesaCtx, mesaDraw); |
||
806 | if (mesaRead != mesaDraw) |
||
807 | swrast_check_and_update_window_size(mesaCtx, mesaRead); |
||
808 | |||
809 | _mesa_make_current( mesaCtx, |
||
810 | mesaDraw, |
||
811 | mesaRead ); |
||
812 | } |
||
813 | else { |
||
814 | /* unbind */ |
||
815 | _mesa_make_current( NULL, NULL, NULL ); |
||
816 | } |
||
817 | |||
818 | return GL_TRUE; |
||
819 | } |
||
820 | |||
821 | static GLboolean |
||
822 | dri_unbind_context(__DRIcontext * cPriv) |
||
823 | { |
||
824 | TRACE; |
||
825 | (void) cPriv; |
||
826 | |||
827 | /* Unset current context and dispath table */ |
||
828 | _mesa_make_current(NULL, NULL, NULL); |
||
829 | |||
830 | return GL_TRUE; |
||
831 | } |
||
832 | |||
833 | |||
834 | const struct __DriverAPIRec driDriverAPI = { |
||
835 | .InitScreen = dri_init_screen, |
||
836 | .DestroyScreen = dri_destroy_screen, |
||
837 | .CreateContext = dri_create_context, |
||
838 | .DestroyContext = dri_destroy_context, |
||
839 | .CreateBuffer = dri_create_buffer, |
||
840 | .DestroyBuffer = dri_destroy_buffer, |
||
841 | .SwapBuffers = dri_swap_buffers, |
||
842 | .MakeCurrent = dri_make_current, |
||
843 | .UnbindContext = dri_unbind_context, |
||
844 | }; |
||
845 | |||
846 | /* This is the table of extensions that the loader will dlsym() for. */ |
||
847 | PUBLIC const __DRIextension *__driDriverExtensions[] = { |
||
848 | &driCoreExtension.base, |
||
849 | &driSWRastExtension.base, |
||
850 | NULL |
||
851 | }; |