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