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