• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  * 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 <stdio.h>
36 #include "main/api_exec.h"
37 #include "main/context.h"
38 #include "main/extensions.h"
39 #include "main/fbobject.h"
40 #include "main/formats.h"
41 #include "main/framebuffer.h"
42 #include "main/renderbuffer.h"
43 #include "main/version.h"
44 #include "main/vtxfmt.h"
45 #include "swrast/swrast.h"
46 #include "swrast/s_renderbuffer.h"
47 #include "swrast_setup/swrast_setup.h"
48 #include "tnl/tnl.h"
49 #include "tnl/t_context.h"
50 #include "tnl/t_pipeline.h"
51 #include "vbo/vbo.h"
52 #include "drivers/common/driverfuncs.h"
53 #include "drivers/common/meta.h"
54 #include "utils.h"
55 #include "util/u_memory.h"
56 
57 #include "main/teximage.h"
58 #include "main/texformat.h"
59 #include "main/texobj.h"
60 #include "main/texstate.h"
61 
62 #include "swrast_priv.h"
63 #include "swrast/s_context.h"
64 
65 #include <sys/types.h>
66 #ifdef HAVE_SYS_SYSCTL_H
67 # include <sys/sysctl.h>
68 #endif
69 
70 const __DRIextension **__driDriverGetExtensions_swrast(void);
71 
72 const char * const swrast_vendor_string = "Mesa Project";
73 const char * const swrast_renderer_string = "Software Rasterizer";
74 
75 /**
76  * Screen and config-related functions
77  */
78 
swrastSetTexBuffer2(__DRIcontext * pDRICtx,GLint target,GLint texture_format,__DRIdrawable * dPriv)79 static void swrastSetTexBuffer2(__DRIcontext *pDRICtx, GLint target,
80 				GLint texture_format, __DRIdrawable *dPriv)
81 {
82     struct dri_context *dri_ctx;
83     int x, y, w, h;
84     __DRIscreen *sPriv = dPriv->driScreenPriv;
85     struct gl_texture_object *texObj;
86     struct gl_texture_image *texImage;
87     struct swrast_texture_image *swImage;
88     uint32_t internalFormat;
89     mesa_format texFormat;
90 
91     dri_ctx = pDRICtx->driverPrivate;
92 
93     internalFormat = (texture_format == __DRI_TEXTURE_FORMAT_RGB ? 3 : 4);
94 
95     texObj = _mesa_get_current_tex_object(&dri_ctx->Base, target);
96     texImage = _mesa_get_tex_image(&dri_ctx->Base, texObj, target, 0);
97     swImage = swrast_texture_image(texImage);
98 
99     _mesa_lock_texture(&dri_ctx->Base, texObj);
100 
101     sPriv->swrast_loader->getDrawableInfo(dPriv, &x, &y, &w, &h, dPriv->loaderPrivate);
102 
103     if (texture_format == __DRI_TEXTURE_FORMAT_RGB)
104 	texFormat = MESA_FORMAT_B8G8R8X8_UNORM;
105     else
106 	texFormat = MESA_FORMAT_B8G8R8A8_UNORM;
107 
108     _mesa_init_teximage_fields(&dri_ctx->Base, texImage,
109 			       w, h, 1, 0, internalFormat, texFormat);
110 
111     sPriv->swrast_loader->getImage(dPriv, x, y, w, h, (char *)swImage->Buffer,
112 				   dPriv->loaderPrivate);
113 
114     _mesa_unlock_texture(&dri_ctx->Base, texObj);
115 }
116 
swrastSetTexBuffer(__DRIcontext * pDRICtx,GLint target,__DRIdrawable * dPriv)117 static void swrastSetTexBuffer(__DRIcontext *pDRICtx, GLint target,
118 			       __DRIdrawable *dPriv)
119 {
120     swrastSetTexBuffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv);
121 }
122 
123 static const __DRItexBufferExtension swrastTexBufferExtension = {
124    .base = { __DRI_TEX_BUFFER, 3 },
125 
126    .setTexBuffer        = swrastSetTexBuffer,
127    .setTexBuffer2       = swrastSetTexBuffer2,
128    .releaseTexBuffer    = NULL,
129 };
130 
131 
132 static int
swrast_query_renderer_integer(__DRIscreen * psp,int param,unsigned int * value)133 swrast_query_renderer_integer(__DRIscreen *psp, int param,
134 			       unsigned int *value)
135 {
136    switch (param) {
137    case __DRI2_RENDERER_VENDOR_ID:
138    case __DRI2_RENDERER_DEVICE_ID:
139       /* Return 0xffffffff for both vendor and device id */
140       value[0] = 0xffffffff;
141       return 0;
142    case __DRI2_RENDERER_ACCELERATED:
143       value[0] = 0;
144       return 0;
145    case __DRI2_RENDERER_VIDEO_MEMORY: {
146       /* This should probably share code with os_get_total_physical_memory()
147        * from src/gallium/auxiliary/os/os_misc.c
148        */
149 #if defined(CTL_HW) && defined(HW_MEMSIZE)
150         int mib[2] = { CTL_HW, HW_MEMSIZE };
151         unsigned long system_memory_bytes;
152         size_t len = sizeof(system_memory_bytes);
153         if (sysctl(mib, 2, &system_memory_bytes, &len, NULL, 0) != 0)
154             return -1;
155 #elif defined(_SC_PHYS_PAGES) && defined(_SC_PAGE_SIZE)
156       /* XXX: Do we want to return the full amount of system memory ? */
157       const long system_memory_pages = sysconf(_SC_PHYS_PAGES);
158       const long system_page_size = sysconf(_SC_PAGE_SIZE);
159 
160       if (system_memory_pages <= 0 || system_page_size <= 0)
161          return -1;
162 
163       const uint64_t system_memory_bytes = (uint64_t) system_memory_pages
164          * (uint64_t) system_page_size;
165 #else
166 #error "Unsupported platform"
167 #endif
168 
169       const unsigned system_memory_megabytes =
170          (unsigned) (system_memory_bytes / (1024 * 1024));
171 
172       value[0] = system_memory_megabytes;
173       return 0;
174    }
175    case __DRI2_RENDERER_UNIFIED_MEMORY_ARCHITECTURE:
176       /**
177        * XXX: Perhaps we should return 1 ?
178        * See issue #7 from the spec, currently UNRESOLVED.
179        */
180       value[0] = 0;
181       return 0;
182    default:
183       return driQueryRendererIntegerCommon(psp, param, value);
184    }
185 }
186 
187 static int
swrast_query_renderer_string(__DRIscreen * psp,int param,const char ** value)188 swrast_query_renderer_string(__DRIscreen *psp, int param, const char **value)
189 {
190    switch (param) {
191    case __DRI2_RENDERER_VENDOR_ID:
192       value[0] = swrast_vendor_string;
193       return 0;
194    case __DRI2_RENDERER_DEVICE_ID:
195       value[0] = swrast_renderer_string;
196       return 0;
197    default:
198       return -1;
199    }
200 }
201 
202 static const __DRI2rendererQueryExtension swrast_query_renderer_extension = {
203    .base = { __DRI2_RENDERER_QUERY, 1 },
204 
205    .queryInteger        = swrast_query_renderer_integer,
206    .queryString         = swrast_query_renderer_string
207 };
208 
209 static const __DRIextension *dri_screen_extensions[] = {
210     &swrastTexBufferExtension.base,
211     &swrast_query_renderer_extension.base,
212     &dri2ConfigQueryExtension.base,
213     &dri2NoErrorExtension.base,
214     NULL
215 };
216 
217 static __DRIconfig **
swrastFillInModes(__DRIscreen * psp,unsigned pixel_bits,unsigned depth_bits,unsigned stencil_bits,GLboolean have_back_buffer)218 swrastFillInModes(__DRIscreen *psp,
219 		  unsigned pixel_bits, unsigned depth_bits,
220 		  unsigned stencil_bits, GLboolean have_back_buffer)
221 {
222     __DRIconfig **configs;
223     unsigned depth_buffer_factor;
224     unsigned back_buffer_factor;
225     mesa_format format;
226 
227     static const GLenum back_buffer_modes[] = {
228 	__DRI_ATTRIB_SWAP_NONE, __DRI_ATTRIB_SWAP_UNDEFINED
229     };
230 
231     uint8_t depth_bits_array[4];
232     uint8_t stencil_bits_array[4];
233     uint8_t msaa_samples_array[1];
234 
235     (void) psp;
236     (void) have_back_buffer;
237 
238     depth_bits_array[0] = 0;
239     depth_bits_array[1] = 0;
240     depth_bits_array[2] = depth_bits;
241     depth_bits_array[3] = depth_bits;
242 
243     /* Just like with the accumulation buffer, always provide some modes
244      * with a stencil buffer.
245      */
246     stencil_bits_array[0] = 0;
247     stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
248     stencil_bits_array[2] = 0;
249     stencil_bits_array[3] = (stencil_bits == 0) ? 8 : stencil_bits;
250 
251     msaa_samples_array[0] = 0;
252 
253     depth_buffer_factor = 4;
254     back_buffer_factor = 2;
255 
256     switch (pixel_bits) {
257     case 16:
258 	format = MESA_FORMAT_B5G6R5_UNORM;
259 	break;
260     case 24:
261         format = MESA_FORMAT_B8G8R8X8_UNORM;
262 	break;
263     case 32:
264 	format = MESA_FORMAT_B8G8R8A8_UNORM;
265 	break;
266     default:
267 	fprintf(stderr, "[%s:%u] bad depth %d\n", __func__, __LINE__,
268 		pixel_bits);
269 	return NULL;
270     }
271 
272     configs = driCreateConfigs(format,
273 			       depth_bits_array, stencil_bits_array,
274 			       depth_buffer_factor, back_buffer_modes,
275 			       back_buffer_factor, msaa_samples_array, 1,
276 			       GL_TRUE, GL_FALSE, GL_FALSE);
277     if (configs == NULL) {
278 	fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
279 		__LINE__);
280 	return NULL;
281     }
282 
283     return configs;
284 }
285 
286 static const __DRIconfig **
dri_init_screen(__DRIscreen * psp)287 dri_init_screen(__DRIscreen * psp)
288 {
289     __DRIconfig **configs16, **configs24, **configs32;
290 
291     TRACE;
292 
293     psp->max_gl_compat_version = 21;
294     psp->max_gl_es1_version = 11;
295     psp->max_gl_es2_version = 20;
296 
297     psp->extensions = dri_screen_extensions;
298 
299     configs16 = swrastFillInModes(psp, 16, 16, 0, 1);
300     configs24 = swrastFillInModes(psp, 24, 24, 8, 1);
301     configs32 = swrastFillInModes(psp, 32, 24, 8, 1);
302 
303     configs24 = driConcatConfigs(configs16, configs24);
304     configs32 = driConcatConfigs(configs24, configs32);
305 
306     return (const __DRIconfig **)configs32;
307 }
308 
309 static void
dri_destroy_screen(__DRIscreen * sPriv)310 dri_destroy_screen(__DRIscreen * sPriv)
311 {
312     TRACE;
313     (void) sPriv;
314 }
315 
316 
317 /**
318  * Framebuffer and renderbuffer-related functions.
319  */
320 
321 static GLuint
choose_pixel_format(const struct gl_config * v)322 choose_pixel_format(const struct gl_config *v)
323 {
324     int depth = v->rgbBits;
325 
326     if (depth == 32
327 	&& v->redMask   == 0xff0000
328 	&& v->greenMask == 0x00ff00
329 	&& v->blueMask  == 0x0000ff)
330 	return PF_A8R8G8B8;
331     else if (depth == 24
332 	     && v->redMask   == 0xff0000
333 	     && v->greenMask == 0x00ff00
334 	     && v->blueMask  == 0x0000ff)
335 	return PF_X8R8G8B8;
336     else if (depth == 16
337 	     && v->redMask   == 0xf800
338 	     && v->greenMask == 0x07e0
339 	     && v->blueMask  == 0x001f)
340 	return PF_R5G6B5;
341     else if (depth == 8
342 	     && v->redMask   == 0x07
343 	     && v->greenMask == 0x38
344 	     && v->blueMask  == 0xc0)
345 	return PF_R3G3B2;
346 
347     _mesa_problem( NULL, "unexpected format in %s", __func__ );
348     return 0;
349 }
350 
351 static void
swrast_delete_renderbuffer(struct gl_context * ctx,struct gl_renderbuffer * rb)352 swrast_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
353 {
354     struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb);
355 
356     TRACE;
357 
358     free(xrb->Base.Buffer);
359     _mesa_delete_renderbuffer(ctx, rb);
360 }
361 
362 /* see bytes_per_line in libGL */
363 static inline int
bytes_per_line(unsigned pitch_bits,unsigned mul)364 bytes_per_line(unsigned pitch_bits, unsigned mul)
365 {
366    unsigned mask = mul - 1;
367 
368    return ((pitch_bits + mask) & ~mask) / 8;
369 }
370 
371 static GLboolean
swrast_alloc_front_storage(struct gl_context * ctx,struct gl_renderbuffer * rb,GLenum internalFormat,GLuint width,GLuint height)372 swrast_alloc_front_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
373 			   GLenum internalFormat, GLuint width, GLuint height)
374 {
375     struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb);
376 
377     TRACE;
378 
379     (void) ctx;
380     (void) internalFormat;
381 
382     xrb->Base.Buffer = NULL;
383     rb->Width = width;
384     rb->Height = height;
385     xrb->pitch = bytes_per_line(width * xrb->bpp, 32);
386 
387     return GL_TRUE;
388 }
389 
390 static GLboolean
swrast_alloc_back_storage(struct gl_context * ctx,struct gl_renderbuffer * rb,GLenum internalFormat,GLuint width,GLuint height)391 swrast_alloc_back_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
392 			  GLenum internalFormat, GLuint width, GLuint height)
393 {
394     struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb);
395 
396     TRACE;
397 
398     free(xrb->Base.Buffer);
399 
400     swrast_alloc_front_storage(ctx, rb, internalFormat, width, height);
401 
402     xrb->Base.Buffer = malloc(height * xrb->pitch);
403 
404     return GL_TRUE;
405 }
406 
407 static struct dri_swrast_renderbuffer *
swrast_new_renderbuffer(const struct gl_config * visual,__DRIdrawable * dPriv,GLboolean front)408 swrast_new_renderbuffer(const struct gl_config *visual, __DRIdrawable *dPriv,
409 			GLboolean front)
410 {
411     struct dri_swrast_renderbuffer *xrb = calloc(1, sizeof *xrb);
412     struct gl_renderbuffer *rb;
413     GLuint pixel_format;
414 
415     TRACE;
416 
417     if (!xrb)
418 	return NULL;
419 
420     rb = &xrb->Base.Base;
421 
422     _mesa_init_renderbuffer(rb, 0);
423 
424     pixel_format = choose_pixel_format(visual);
425 
426     xrb->dPriv = dPriv;
427     xrb->Base.Base.Delete = swrast_delete_renderbuffer;
428     if (front) {
429         rb->AllocStorage = swrast_alloc_front_storage;
430     }
431     else {
432 	rb->AllocStorage = swrast_alloc_back_storage;
433     }
434 
435     switch (pixel_format) {
436     case PF_A8R8G8B8:
437 	rb->Format = MESA_FORMAT_B8G8R8A8_UNORM;
438 	rb->InternalFormat = GL_RGBA;
439 	rb->_BaseFormat = GL_RGBA;
440 	xrb->bpp = 32;
441 	break;
442     case PF_X8R8G8B8:
443 	rb->Format = MESA_FORMAT_B8G8R8A8_UNORM; /* XXX */
444 	rb->InternalFormat = GL_RGB;
445 	rb->_BaseFormat = GL_RGB;
446 	xrb->bpp = 32;
447 	break;
448     case PF_R5G6B5:
449 	rb->Format = MESA_FORMAT_B5G6R5_UNORM;
450 	rb->InternalFormat = GL_RGB;
451 	rb->_BaseFormat = GL_RGB;
452 	xrb->bpp = 16;
453 	break;
454     case PF_R3G3B2:
455 	rb->Format = MESA_FORMAT_B2G3R3_UNORM;
456 	rb->InternalFormat = GL_RGB;
457 	rb->_BaseFormat = GL_RGB;
458 	xrb->bpp = 8;
459 	break;
460     default:
461 	free(xrb);
462 	return NULL;
463     }
464 
465     return xrb;
466 }
467 
468 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,bool flip_y)469 swrast_map_renderbuffer(struct gl_context *ctx,
470 			struct gl_renderbuffer *rb,
471 			GLuint x, GLuint y, GLuint w, GLuint h,
472 			GLbitfield mode,
473 			GLubyte **out_map,
474 			GLint *out_stride,
475 			bool flip_y)
476 {
477    struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb);
478    GLubyte *map = xrb->Base.Buffer;
479    int cpp = _mesa_get_format_bytes(rb->Format);
480    int stride = rb->Width * cpp;
481 
482    /* driver does not support GL_FRAMEBUFFER_FLIP_Y_MESA */
483    assert((rb->Name == 0) == flip_y);
484 
485    if (rb->AllocStorage == swrast_alloc_front_storage) {
486       __DRIdrawable *dPriv = xrb->dPriv;
487       __DRIscreen *sPriv = dPriv->driScreenPriv;
488 
489       xrb->map_mode = mode;
490       xrb->map_x = x;
491       xrb->map_y = rb->Height - y - h;
492       xrb->map_w = w;
493       xrb->map_h = h;
494 
495       stride = w * cpp;
496       xrb->Base.Buffer = malloc(h * stride);
497 
498       sPriv->swrast_loader->getImage(dPriv, x, xrb->map_y, w, h,
499 				     (char *) xrb->Base.Buffer,
500 				     dPriv->loaderPrivate);
501 
502       *out_map = xrb->Base.Buffer + (h - 1) * stride;
503       *out_stride = -stride;
504       return;
505    }
506 
507    assert(xrb->Base.Buffer);
508 
509    if (rb->AllocStorage == swrast_alloc_back_storage) {
510       map += (rb->Height - 1) * stride;
511       stride = -stride;
512    }
513 
514    map += (GLsizei)y * stride;
515    map += (GLsizei)x * cpp;
516 
517    *out_map = map;
518    *out_stride = stride;
519 }
520 
521 static void
swrast_unmap_renderbuffer(struct gl_context * ctx,struct gl_renderbuffer * rb)522 swrast_unmap_renderbuffer(struct gl_context *ctx,
523 			  struct gl_renderbuffer *rb)
524 {
525    struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb);
526 
527    if (rb->AllocStorage == swrast_alloc_front_storage) {
528       __DRIdrawable *dPriv = xrb->dPriv;
529       __DRIscreen *sPriv = dPriv->driScreenPriv;
530 
531       if (xrb->map_mode & GL_MAP_WRITE_BIT) {
532 	 sPriv->swrast_loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_DRAW,
533 					xrb->map_x, xrb->map_y,
534 					xrb->map_w, xrb->map_h,
535 					(char *) xrb->Base.Buffer,
536 					dPriv->loaderPrivate);
537       }
538 
539       free(xrb->Base.Buffer);
540       xrb->Base.Buffer = NULL;
541    }
542 }
543 
544 static GLboolean
dri_create_buffer(__DRIscreen * sPriv,__DRIdrawable * dPriv,const struct gl_config * visual,GLboolean isPixmap)545 dri_create_buffer(__DRIscreen * sPriv,
546 		  __DRIdrawable * dPriv,
547 		  const struct gl_config * visual, GLboolean isPixmap)
548 {
549     struct dri_drawable *drawable = NULL;
550     struct gl_framebuffer *fb;
551     struct dri_swrast_renderbuffer *frontrb, *backrb;
552 
553     TRACE;
554 
555     (void) sPriv;
556     (void) isPixmap;
557 
558     drawable = CALLOC_STRUCT(dri_drawable);
559     if (drawable == NULL)
560 	goto drawable_fail;
561 
562     dPriv->driverPrivate = drawable;
563     drawable->dPriv = dPriv;
564 
565     drawable->row = malloc(SWRAST_MAX_WIDTH * 4);
566     if (drawable->row == NULL)
567 	goto drawable_fail;
568 
569     fb = &drawable->Base;
570 
571     /* basic framebuffer setup */
572     _mesa_initialize_window_framebuffer(fb, visual);
573 
574     /* add front renderbuffer */
575     frontrb = swrast_new_renderbuffer(visual, dPriv, GL_TRUE);
576     _mesa_attach_and_own_rb(fb, BUFFER_FRONT_LEFT, &frontrb->Base.Base);
577 
578     /* add back renderbuffer */
579     if (visual->doubleBufferMode) {
580 	backrb = swrast_new_renderbuffer(visual, dPriv, GL_FALSE);
581         _mesa_attach_and_own_rb(fb, BUFFER_BACK_LEFT, &backrb->Base.Base);
582     }
583 
584     /* add software renderbuffers */
585     _swrast_add_soft_renderbuffers(fb,
586                                    GL_FALSE, /* color */
587                                    visual->depthBits > 0,
588                                    visual->stencilBits > 0,
589                                    visual->accumRedBits > 0,
590                                    GL_FALSE, /* alpha */
591                                    GL_FALSE /* aux bufs */);
592 
593     return GL_TRUE;
594 
595 drawable_fail:
596 
597     if (drawable)
598 	free(drawable->row);
599 
600     free(drawable);
601 
602     return GL_FALSE;
603 }
604 
605 static void
dri_destroy_buffer(__DRIdrawable * dPriv)606 dri_destroy_buffer(__DRIdrawable * dPriv)
607 {
608     TRACE;
609 
610     if (dPriv) {
611 	struct dri_drawable *drawable = dri_drawable(dPriv);
612 	struct gl_framebuffer *fb;
613 
614 	free(drawable->row);
615 
616 	fb = &drawable->Base;
617 
618 	fb->DeletePending = GL_TRUE;
619 	_mesa_reference_framebuffer(&fb, NULL);
620     }
621 }
622 
623 static void
dri_swap_buffers(__DRIdrawable * dPriv)624 dri_swap_buffers(__DRIdrawable * dPriv)
625 {
626     __DRIscreen *sPriv = dPriv->driScreenPriv;
627 
628     GET_CURRENT_CONTEXT(ctx);
629 
630     struct dri_drawable *drawable = dri_drawable(dPriv);
631     struct gl_framebuffer *fb;
632     struct dri_swrast_renderbuffer *frontrb, *backrb;
633 
634     TRACE;
635 
636     fb = &drawable->Base;
637 
638     frontrb =
639 	dri_swrast_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
640     backrb =
641 	dri_swrast_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
642 
643     /* check for signle-buffered */
644     if (backrb == NULL)
645 	return;
646 
647     /* check if swapping currently bound buffer */
648     if (ctx && ctx->DrawBuffer == fb) {
649 	/* flush pending rendering */
650 	_mesa_notifySwapBuffers(ctx);
651     }
652 
653     sPriv->swrast_loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP,
654 				   0, 0,
655 				   frontrb->Base.Base.Width,
656 				   frontrb->Base.Base.Height,
657 				   (char *) backrb->Base.Buffer,
658 				   dPriv->loaderPrivate);
659 }
660 
661 
662 /**
663  * General device driver functions.
664  */
665 
666 static void
get_window_size(struct gl_framebuffer * fb,GLsizei * w,GLsizei * h)667 get_window_size( struct gl_framebuffer *fb, GLsizei *w, GLsizei *h )
668 {
669     __DRIdrawable *dPriv = swrast_drawable(fb)->dPriv;
670     __DRIscreen *sPriv = dPriv->driScreenPriv;
671     int x, y;
672 
673     sPriv->swrast_loader->getDrawableInfo(dPriv,
674 					  &x, &y, w, h,
675 					  dPriv->loaderPrivate);
676 }
677 
678 static void
swrast_check_and_update_window_size(struct gl_context * ctx,struct gl_framebuffer * fb)679 swrast_check_and_update_window_size( struct gl_context *ctx, struct gl_framebuffer *fb )
680 {
681     GLsizei width, height;
682 
683     if (!fb || fb == _mesa_get_incomplete_framebuffer())
684         return;
685 
686     get_window_size(fb, &width, &height);
687     if (fb->Width != width || fb->Height != height) {
688 	_mesa_resize_framebuffer(ctx, fb, width, height);
689     }
690 }
691 
692 static const GLubyte *
get_string(struct gl_context * ctx,GLenum pname)693 get_string(struct gl_context *ctx, GLenum pname)
694 {
695     (void) ctx;
696     switch (pname) {
697 	case GL_VENDOR:
698 	    return (const GLubyte *) swrast_vendor_string;
699 	case GL_RENDERER:
700 	    return (const GLubyte *) swrast_renderer_string;
701 	default:
702 	    return NULL;
703     }
704 }
705 
706 static void
update_state(struct gl_context * ctx)707 update_state(struct gl_context *ctx)
708 {
709     GLuint new_state = ctx->NewState;
710 
711     if (new_state & (_NEW_SCISSOR | _NEW_BUFFERS | _NEW_VIEWPORT))
712       _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer);
713 
714     /* not much to do here - pass it on */
715     _swrast_InvalidateState( ctx, new_state );
716     _swsetup_InvalidateState( ctx, new_state );
717     _tnl_InvalidateState( ctx, new_state );
718 }
719 
720 static void
viewport(struct gl_context * ctx)721 viewport(struct gl_context *ctx)
722 {
723     struct gl_framebuffer *draw = ctx->WinSysDrawBuffer;
724     struct gl_framebuffer *read = ctx->WinSysReadBuffer;
725 
726     swrast_check_and_update_window_size(ctx, draw);
727     swrast_check_and_update_window_size(ctx, read);
728 }
729 
swrastChooseTextureFormat(struct gl_context * ctx,GLenum target,GLint internalFormat,GLenum format,GLenum type)730 static mesa_format swrastChooseTextureFormat(struct gl_context * ctx,
731                                            GLenum target,
732 					   GLint internalFormat,
733 					   GLenum format,
734 					   GLenum type)
735 {
736     if (internalFormat == GL_RGB)
737 	return MESA_FORMAT_B8G8R8X8_UNORM;
738     return _mesa_choose_tex_format(ctx, target, internalFormat, format, type);
739 }
740 
741 static void
swrast_init_driver_functions(struct dd_function_table * driver)742 swrast_init_driver_functions(struct dd_function_table *driver)
743 {
744     driver->GetString = get_string;
745     driver->UpdateState = update_state;
746     driver->Viewport = viewport;
747     driver->ChooseTextureFormat = swrastChooseTextureFormat;
748     driver->MapRenderbuffer = swrast_map_renderbuffer;
749     driver->UnmapRenderbuffer = swrast_unmap_renderbuffer;
750 }
751 
752 /**
753  * Context-related functions.
754  */
755 
756 static GLboolean
dri_create_context(gl_api api,const struct gl_config * visual,__DRIcontext * cPriv,const struct __DriverContextConfig * ctx_config,unsigned * error,void * sharedContextPrivate)757 dri_create_context(gl_api api,
758 		   const struct gl_config * visual,
759 		   __DRIcontext * cPriv,
760 		   const struct __DriverContextConfig *ctx_config,
761 		   unsigned *error,
762 		   void *sharedContextPrivate)
763 {
764     struct dri_context *ctx = NULL;
765     struct dri_context *share = (struct dri_context *)sharedContextPrivate;
766     struct gl_context *mesaCtx = NULL;
767     struct gl_context *sharedCtx = NULL;
768     struct dd_function_table functions;
769 
770     TRACE;
771 
772     /* Flag filtering is handled in dri2CreateContextAttribs.
773      */
774     (void) ctx_config->flags;
775 
776     /* The swrast driver doesn't understand any of the attributes */
777     if (ctx_config->attribute_mask != 0) {
778 	*error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE;
779 	return false;
780     }
781 
782     ctx = CALLOC_STRUCT(dri_context);
783     if (ctx == NULL) {
784 	*error = __DRI_CTX_ERROR_NO_MEMORY;
785 	goto context_fail;
786     }
787 
788     cPriv->driverPrivate = ctx;
789     ctx->cPriv = cPriv;
790 
791     /* build table of device driver functions */
792     _mesa_init_driver_functions(&functions);
793     swrast_init_driver_functions(&functions);
794     _tnl_init_driver_draw_function(&functions);
795 
796     if (share) {
797 	sharedCtx = &share->Base;
798     }
799 
800     mesaCtx = &ctx->Base;
801 
802     /* basic context setup */
803     if (!_mesa_initialize_context(mesaCtx, api, visual, sharedCtx, &functions)) {
804 	*error = __DRI_CTX_ERROR_NO_MEMORY;
805 	goto context_fail;
806     }
807 
808     driContextSetFlags(mesaCtx, ctx_config->flags);
809 
810     /* create module contexts */
811     _swrast_CreateContext( mesaCtx );
812     _vbo_CreateContext( mesaCtx, false );
813     _tnl_CreateContext( mesaCtx );
814     _swsetup_CreateContext( mesaCtx );
815     _swsetup_Wakeup( mesaCtx );
816 
817     /* use default TCL pipeline */
818     {
819        TNLcontext *tnl = TNL_CONTEXT(mesaCtx);
820        tnl->Driver.RunPipeline = _tnl_run_pipeline;
821     }
822 
823     _mesa_meta_init(mesaCtx);
824     _mesa_enable_sw_extensions(mesaCtx);
825 
826    _mesa_override_extensions(mesaCtx);
827     _mesa_compute_version(mesaCtx);
828 
829     _mesa_initialize_dispatch_tables(mesaCtx);
830     _mesa_initialize_vbo_vtxfmt(mesaCtx);
831 
832     *error = __DRI_CTX_ERROR_SUCCESS;
833     return GL_TRUE;
834 
835 context_fail:
836 
837     free(ctx);
838 
839     return GL_FALSE;
840 }
841 
842 static void
dri_destroy_context(__DRIcontext * cPriv)843 dri_destroy_context(__DRIcontext * cPriv)
844 {
845     TRACE;
846 
847     if (cPriv) {
848 	struct dri_context *ctx = dri_context(cPriv);
849 	struct gl_context *mesaCtx;
850 
851 	mesaCtx = &ctx->Base;
852 
853         _mesa_meta_free(mesaCtx);
854 	_swsetup_DestroyContext( mesaCtx );
855 	_swrast_DestroyContext( mesaCtx );
856 	_tnl_DestroyContext( mesaCtx );
857 	_vbo_DestroyContext( mesaCtx );
858 	_mesa_destroy_context( mesaCtx );
859     }
860 }
861 
862 static GLboolean
dri_make_current(__DRIcontext * cPriv,__DRIdrawable * driDrawPriv,__DRIdrawable * driReadPriv)863 dri_make_current(__DRIcontext * cPriv,
864 		 __DRIdrawable * driDrawPriv,
865 		 __DRIdrawable * driReadPriv)
866 {
867     struct gl_context *mesaCtx;
868     struct gl_framebuffer *mesaDraw = NULL;
869     struct gl_framebuffer *mesaRead = NULL;
870     TRACE;
871 
872     if (cPriv) {
873         mesaCtx = &dri_context(cPriv)->Base;
874 
875 	if (driDrawPriv && driReadPriv) {
876            struct dri_drawable *draw = dri_drawable(driDrawPriv);
877            struct dri_drawable *read = dri_drawable(driReadPriv);
878            mesaDraw = &draw->Base;
879            mesaRead = &read->Base;
880         }
881         else {
882            struct gl_framebuffer *incomplete
883               = _mesa_get_incomplete_framebuffer();
884            mesaDraw = incomplete;
885            mesaRead = incomplete;
886         }
887 
888         /* check for same context and buffer */
889         if (mesaCtx == _mesa_get_current_context()
890             && mesaCtx->DrawBuffer == mesaDraw
891             && mesaCtx->ReadBuffer == mesaRead) {
892             return GL_TRUE;
893         }
894 
895 	swrast_check_and_update_window_size(mesaCtx, mesaDraw);
896 	if (mesaRead != mesaDraw)
897 	    swrast_check_and_update_window_size(mesaCtx, mesaRead);
898 
899 	_mesa_make_current( mesaCtx,
900 			    mesaDraw,
901 			    mesaRead );
902     }
903     else {
904 	/* unbind */
905 	_mesa_make_current( NULL, NULL, NULL );
906     }
907 
908     return GL_TRUE;
909 }
910 
911 static GLboolean
dri_unbind_context(__DRIcontext * cPriv)912 dri_unbind_context(__DRIcontext * cPriv)
913 {
914     TRACE;
915     (void) cPriv;
916 
917     /* Unset current context and dispath table */
918     _mesa_make_current(NULL, NULL, NULL);
919 
920     return GL_TRUE;
921 }
922 
923 static void
dri_copy_sub_buffer(__DRIdrawable * dPriv,int x,int y,int w,int h)924 dri_copy_sub_buffer(__DRIdrawable *dPriv, int x, int y,
925                     int w, int h)
926 {
927     __DRIscreen *sPriv = dPriv->driScreenPriv;
928     void *data;
929     int iy;
930     struct dri_drawable *drawable = dri_drawable(dPriv);
931     struct gl_framebuffer *fb;
932     struct dri_swrast_renderbuffer *frontrb, *backrb;
933 
934     TRACE;
935 
936     fb = &drawable->Base;
937 
938     frontrb =
939 	dri_swrast_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
940     backrb =
941 	dri_swrast_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
942 
943     /* check for signle-buffered */
944     if (backrb == NULL)
945        return;
946 
947     iy = frontrb->Base.Base.Height - y - h;
948     data = (char *)backrb->Base.Buffer + (iy * backrb->pitch) + (x * ((backrb->bpp + 7) / 8));
949     sPriv->swrast_loader->putImage2(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP,
950                                     x, iy, w, h,
951                                     frontrb->pitch,
952                                     data,
953                                     dPriv->loaderPrivate);
954 }
955 
956 
957 static const struct __DriverAPIRec swrast_driver_api = {
958     .InitScreen = dri_init_screen,
959     .DestroyScreen = dri_destroy_screen,
960     .CreateContext = dri_create_context,
961     .DestroyContext = dri_destroy_context,
962     .CreateBuffer = dri_create_buffer,
963     .DestroyBuffer = dri_destroy_buffer,
964     .SwapBuffers = dri_swap_buffers,
965     .MakeCurrent = dri_make_current,
966     .UnbindContext = dri_unbind_context,
967     .CopySubBuffer = dri_copy_sub_buffer,
968 };
969 
970 static const struct __DRIDriverVtableExtensionRec swrast_vtable = {
971    .base = { __DRI_DRIVER_VTABLE, 1 },
972    .vtable = &swrast_driver_api,
973 };
974 
975 static const __DRIextension *swrast_driver_extensions[] = {
976     &driCoreExtension.base,
977     &driSWRastExtension.base,
978     &driCopySubBufferExtension.base,
979     &swrast_vtable.base,
980     NULL
981 };
982 
__driDriverGetExtensions_swrast(void)983 PUBLIC const __DRIextension **__driDriverGetExtensions_swrast(void)
984 {
985    globalDriverAPI = &swrast_driver_api;
986 
987    return swrast_driver_extensions;
988 }
989