• 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     NULL
212 };
213 
214 static __DRIconfig **
swrastFillInModes(__DRIscreen * psp,unsigned pixel_bits,unsigned depth_bits,unsigned stencil_bits,GLboolean have_back_buffer)215 swrastFillInModes(__DRIscreen *psp,
216 		  unsigned pixel_bits, unsigned depth_bits,
217 		  unsigned stencil_bits, GLboolean have_back_buffer)
218 {
219     __DRIconfig **configs;
220     unsigned depth_buffer_factor;
221     unsigned back_buffer_factor;
222     mesa_format format;
223 
224     /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
225      * support pageflipping at all.
226      */
227     static const GLenum back_buffer_modes[] = {
228 	GLX_NONE, GLX_SWAP_UNDEFINED_OML
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);
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)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 {
476    struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb);
477    GLubyte *map = xrb->Base.Buffer;
478    int cpp = _mesa_get_format_bytes(rb->Format);
479    int stride = rb->Width * cpp;
480 
481    if (rb->AllocStorage == swrast_alloc_front_storage) {
482       __DRIdrawable *dPriv = xrb->dPriv;
483       __DRIscreen *sPriv = dPriv->driScreenPriv;
484 
485       xrb->map_mode = mode;
486       xrb->map_x = x;
487       xrb->map_y = rb->Height - y - h;
488       xrb->map_w = w;
489       xrb->map_h = h;
490 
491       stride = w * cpp;
492       xrb->Base.Buffer = malloc(h * stride);
493 
494       sPriv->swrast_loader->getImage(dPriv, x, xrb->map_y, w, h,
495 				     (char *) xrb->Base.Buffer,
496 				     dPriv->loaderPrivate);
497 
498       *out_map = xrb->Base.Buffer + (h - 1) * stride;
499       *out_stride = -stride;
500       return;
501    }
502 
503    assert(xrb->Base.Buffer);
504 
505    if (rb->AllocStorage == swrast_alloc_back_storage) {
506       map += (rb->Height - 1) * stride;
507       stride = -stride;
508    }
509 
510    map += (GLsizei)y * stride;
511    map += (GLsizei)x * cpp;
512 
513    *out_map = map;
514    *out_stride = stride;
515 }
516 
517 static void
swrast_unmap_renderbuffer(struct gl_context * ctx,struct gl_renderbuffer * rb)518 swrast_unmap_renderbuffer(struct gl_context *ctx,
519 			  struct gl_renderbuffer *rb)
520 {
521    struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb);
522 
523    if (rb->AllocStorage == swrast_alloc_front_storage) {
524       __DRIdrawable *dPriv = xrb->dPriv;
525       __DRIscreen *sPriv = dPriv->driScreenPriv;
526 
527       if (xrb->map_mode & GL_MAP_WRITE_BIT) {
528 	 sPriv->swrast_loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_DRAW,
529 					xrb->map_x, xrb->map_y,
530 					xrb->map_w, xrb->map_h,
531 					(char *) xrb->Base.Buffer,
532 					dPriv->loaderPrivate);
533       }
534 
535       free(xrb->Base.Buffer);
536       xrb->Base.Buffer = NULL;
537    }
538 }
539 
540 static GLboolean
dri_create_buffer(__DRIscreen * sPriv,__DRIdrawable * dPriv,const struct gl_config * visual,GLboolean isPixmap)541 dri_create_buffer(__DRIscreen * sPriv,
542 		  __DRIdrawable * dPriv,
543 		  const struct gl_config * visual, GLboolean isPixmap)
544 {
545     struct dri_drawable *drawable = NULL;
546     struct gl_framebuffer *fb;
547     struct dri_swrast_renderbuffer *frontrb, *backrb;
548 
549     TRACE;
550 
551     (void) sPriv;
552     (void) isPixmap;
553 
554     drawable = CALLOC_STRUCT(dri_drawable);
555     if (drawable == NULL)
556 	goto drawable_fail;
557 
558     dPriv->driverPrivate = drawable;
559     drawable->dPriv = dPriv;
560 
561     drawable->row = malloc(SWRAST_MAX_WIDTH * 4);
562     if (drawable->row == NULL)
563 	goto drawable_fail;
564 
565     fb = &drawable->Base;
566 
567     /* basic framebuffer setup */
568     _mesa_initialize_window_framebuffer(fb, visual);
569 
570     /* add front renderbuffer */
571     frontrb = swrast_new_renderbuffer(visual, dPriv, GL_TRUE);
572     _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontrb->Base.Base);
573 
574     /* add back renderbuffer */
575     if (visual->doubleBufferMode) {
576 	backrb = swrast_new_renderbuffer(visual, dPriv, GL_FALSE);
577 	_mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backrb->Base.Base);
578     }
579 
580     /* add software renderbuffers */
581     _swrast_add_soft_renderbuffers(fb,
582                                    GL_FALSE, /* color */
583                                    visual->haveDepthBuffer,
584                                    visual->haveStencilBuffer,
585                                    visual->haveAccumBuffer,
586                                    GL_FALSE, /* alpha */
587                                    GL_FALSE /* aux bufs */);
588 
589     return GL_TRUE;
590 
591 drawable_fail:
592 
593     if (drawable)
594 	free(drawable->row);
595 
596     free(drawable);
597 
598     return GL_FALSE;
599 }
600 
601 static void
dri_destroy_buffer(__DRIdrawable * dPriv)602 dri_destroy_buffer(__DRIdrawable * dPriv)
603 {
604     TRACE;
605 
606     if (dPriv) {
607 	struct dri_drawable *drawable = dri_drawable(dPriv);
608 	struct gl_framebuffer *fb;
609 
610 	free(drawable->row);
611 
612 	fb = &drawable->Base;
613 
614 	fb->DeletePending = GL_TRUE;
615 	_mesa_reference_framebuffer(&fb, NULL);
616     }
617 }
618 
619 static void
dri_swap_buffers(__DRIdrawable * dPriv)620 dri_swap_buffers(__DRIdrawable * dPriv)
621 {
622     __DRIscreen *sPriv = dPriv->driScreenPriv;
623 
624     GET_CURRENT_CONTEXT(ctx);
625 
626     struct dri_drawable *drawable = dri_drawable(dPriv);
627     struct gl_framebuffer *fb;
628     struct dri_swrast_renderbuffer *frontrb, *backrb;
629 
630     TRACE;
631 
632     fb = &drawable->Base;
633 
634     frontrb =
635 	dri_swrast_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
636     backrb =
637 	dri_swrast_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
638 
639     /* check for signle-buffered */
640     if (backrb == NULL)
641 	return;
642 
643     /* check if swapping currently bound buffer */
644     if (ctx && ctx->DrawBuffer == fb) {
645 	/* flush pending rendering */
646 	_mesa_notifySwapBuffers(ctx);
647     }
648 
649     sPriv->swrast_loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP,
650 				   0, 0,
651 				   frontrb->Base.Base.Width,
652 				   frontrb->Base.Base.Height,
653 				   (char *) backrb->Base.Buffer,
654 				   dPriv->loaderPrivate);
655 }
656 
657 
658 /**
659  * General device driver functions.
660  */
661 
662 static void
get_window_size(struct gl_framebuffer * fb,GLsizei * w,GLsizei * h)663 get_window_size( struct gl_framebuffer *fb, GLsizei *w, GLsizei *h )
664 {
665     __DRIdrawable *dPriv = swrast_drawable(fb)->dPriv;
666     __DRIscreen *sPriv = dPriv->driScreenPriv;
667     int x, y;
668 
669     sPriv->swrast_loader->getDrawableInfo(dPriv,
670 					  &x, &y, w, h,
671 					  dPriv->loaderPrivate);
672 }
673 
674 static void
swrast_check_and_update_window_size(struct gl_context * ctx,struct gl_framebuffer * fb)675 swrast_check_and_update_window_size( struct gl_context *ctx, struct gl_framebuffer *fb )
676 {
677     GLsizei width, height;
678 
679     get_window_size(fb, &width, &height);
680     if (fb->Width != width || fb->Height != height) {
681 	_mesa_resize_framebuffer(ctx, fb, width, height);
682     }
683 }
684 
685 static const GLubyte *
get_string(struct gl_context * ctx,GLenum pname)686 get_string(struct gl_context *ctx, GLenum pname)
687 {
688     (void) ctx;
689     switch (pname) {
690 	case GL_VENDOR:
691 	    return (const GLubyte *) swrast_vendor_string;
692 	case GL_RENDERER:
693 	    return (const GLubyte *) swrast_renderer_string;
694 	default:
695 	    return NULL;
696     }
697 }
698 
699 static void
update_state(struct gl_context * ctx,GLuint new_state)700 update_state( struct gl_context *ctx, GLuint new_state )
701 {
702     /* not much to do here - pass it on */
703     _swrast_InvalidateState( ctx, new_state );
704     _swsetup_InvalidateState( ctx, new_state );
705     _vbo_InvalidateState( ctx, new_state );
706     _tnl_InvalidateState( ctx, new_state );
707 }
708 
709 static void
viewport(struct gl_context * ctx)710 viewport(struct gl_context *ctx)
711 {
712     struct gl_framebuffer *draw = ctx->WinSysDrawBuffer;
713     struct gl_framebuffer *read = ctx->WinSysReadBuffer;
714 
715     swrast_check_and_update_window_size(ctx, draw);
716     swrast_check_and_update_window_size(ctx, read);
717 }
718 
swrastChooseTextureFormat(struct gl_context * ctx,GLenum target,GLint internalFormat,GLenum format,GLenum type)719 static mesa_format swrastChooseTextureFormat(struct gl_context * ctx,
720                                            GLenum target,
721 					   GLint internalFormat,
722 					   GLenum format,
723 					   GLenum type)
724 {
725     if (internalFormat == GL_RGB)
726 	return MESA_FORMAT_B8G8R8X8_UNORM;
727     return _mesa_choose_tex_format(ctx, target, internalFormat, format, type);
728 }
729 
730 static void
swrast_init_driver_functions(struct dd_function_table * driver)731 swrast_init_driver_functions(struct dd_function_table *driver)
732 {
733     driver->GetString = get_string;
734     driver->UpdateState = update_state;
735     driver->Viewport = viewport;
736     driver->ChooseTextureFormat = swrastChooseTextureFormat;
737     driver->MapRenderbuffer = swrast_map_renderbuffer;
738     driver->UnmapRenderbuffer = swrast_unmap_renderbuffer;
739 }
740 
741 /**
742  * Context-related functions.
743  */
744 
745 static GLboolean
dri_create_context(gl_api api,const struct gl_config * visual,__DRIcontext * cPriv,unsigned major_version,unsigned minor_version,uint32_t flags,bool notify_reset,unsigned * error,void * sharedContextPrivate)746 dri_create_context(gl_api api,
747 		   const struct gl_config * visual,
748 		   __DRIcontext * cPriv,
749 		   unsigned major_version,
750 		   unsigned minor_version,
751 		   uint32_t flags,
752 		   bool notify_reset,
753 		   unsigned *error,
754 		   void *sharedContextPrivate)
755 {
756     struct dri_context *ctx = NULL;
757     struct dri_context *share = (struct dri_context *)sharedContextPrivate;
758     struct gl_context *mesaCtx = NULL;
759     struct gl_context *sharedCtx = NULL;
760     struct dd_function_table functions;
761 
762     TRACE;
763 
764     /* Flag filtering is handled in dri2CreateContextAttribs.
765      */
766     (void) flags;
767 
768     ctx = CALLOC_STRUCT(dri_context);
769     if (ctx == NULL) {
770 	*error = __DRI_CTX_ERROR_NO_MEMORY;
771 	goto context_fail;
772     }
773 
774     cPriv->driverPrivate = ctx;
775     ctx->cPriv = cPriv;
776 
777     /* build table of device driver functions */
778     _mesa_init_driver_functions(&functions);
779     swrast_init_driver_functions(&functions);
780 
781     if (share) {
782 	sharedCtx = &share->Base;
783     }
784 
785     mesaCtx = &ctx->Base;
786 
787     /* basic context setup */
788     if (!_mesa_initialize_context(mesaCtx, api, visual, sharedCtx, &functions)) {
789 	*error = __DRI_CTX_ERROR_NO_MEMORY;
790 	goto context_fail;
791     }
792 
793     driContextSetFlags(mesaCtx, flags);
794 
795     /* create module contexts */
796     _swrast_CreateContext( mesaCtx );
797     _vbo_CreateContext( mesaCtx );
798     _tnl_CreateContext( mesaCtx );
799     _swsetup_CreateContext( mesaCtx );
800     _swsetup_Wakeup( mesaCtx );
801 
802     /* use default TCL pipeline */
803     {
804        TNLcontext *tnl = TNL_CONTEXT(mesaCtx);
805        tnl->Driver.RunPipeline = _tnl_run_pipeline;
806     }
807 
808     _mesa_meta_init(mesaCtx);
809     _mesa_enable_sw_extensions(mesaCtx);
810 
811     _mesa_compute_version(mesaCtx);
812 
813     _mesa_initialize_dispatch_tables(mesaCtx);
814     _mesa_initialize_vbo_vtxfmt(mesaCtx);
815 
816     *error = __DRI_CTX_ERROR_SUCCESS;
817     return GL_TRUE;
818 
819 context_fail:
820 
821     free(ctx);
822 
823     return GL_FALSE;
824 }
825 
826 static void
dri_destroy_context(__DRIcontext * cPriv)827 dri_destroy_context(__DRIcontext * cPriv)
828 {
829     TRACE;
830 
831     if (cPriv) {
832 	struct dri_context *ctx = dri_context(cPriv);
833 	struct gl_context *mesaCtx;
834 
835 	mesaCtx = &ctx->Base;
836 
837         _mesa_meta_free(mesaCtx);
838 	_swsetup_DestroyContext( mesaCtx );
839 	_swrast_DestroyContext( mesaCtx );
840 	_tnl_DestroyContext( mesaCtx );
841 	_vbo_DestroyContext( mesaCtx );
842 	_mesa_destroy_context( mesaCtx );
843     }
844 }
845 
846 static GLboolean
dri_make_current(__DRIcontext * cPriv,__DRIdrawable * driDrawPriv,__DRIdrawable * driReadPriv)847 dri_make_current(__DRIcontext * cPriv,
848 		 __DRIdrawable * driDrawPriv,
849 		 __DRIdrawable * driReadPriv)
850 {
851     struct gl_context *mesaCtx;
852     struct gl_framebuffer *mesaDraw;
853     struct gl_framebuffer *mesaRead;
854     TRACE;
855 
856     if (cPriv) {
857 	struct dri_context *ctx = dri_context(cPriv);
858 	struct dri_drawable *draw;
859 	struct dri_drawable *read;
860 
861 	if (!driDrawPriv || !driReadPriv)
862 	    return GL_FALSE;
863 
864 	draw = dri_drawable(driDrawPriv);
865 	read = dri_drawable(driReadPriv);
866 	mesaCtx = &ctx->Base;
867 	mesaDraw = &draw->Base;
868 	mesaRead = &read->Base;
869 
870 	/* check for same context and buffer */
871 	if (mesaCtx == _mesa_get_current_context()
872 	    && mesaCtx->DrawBuffer == mesaDraw
873 	    && mesaCtx->ReadBuffer == mesaRead) {
874 	    return GL_TRUE;
875 	}
876 
877 	_glapi_check_multithread();
878 
879 	swrast_check_and_update_window_size(mesaCtx, mesaDraw);
880 	if (mesaRead != mesaDraw)
881 	    swrast_check_and_update_window_size(mesaCtx, mesaRead);
882 
883 	_mesa_make_current( mesaCtx,
884 			    mesaDraw,
885 			    mesaRead );
886     }
887     else {
888 	/* unbind */
889 	_mesa_make_current( NULL, NULL, NULL );
890     }
891 
892     return GL_TRUE;
893 }
894 
895 static GLboolean
dri_unbind_context(__DRIcontext * cPriv)896 dri_unbind_context(__DRIcontext * cPriv)
897 {
898     TRACE;
899     (void) cPriv;
900 
901     /* Unset current context and dispath table */
902     _mesa_make_current(NULL, NULL, NULL);
903 
904     return GL_TRUE;
905 }
906 
907 static void
dri_copy_sub_buffer(__DRIdrawable * dPriv,int x,int y,int w,int h)908 dri_copy_sub_buffer(__DRIdrawable *dPriv, int x, int y,
909                     int w, int h)
910 {
911     __DRIscreen *sPriv = dPriv->driScreenPriv;
912     void *data;
913     int iy;
914     struct dri_drawable *drawable = dri_drawable(dPriv);
915     struct gl_framebuffer *fb;
916     struct dri_swrast_renderbuffer *frontrb, *backrb;
917 
918     TRACE;
919 
920     fb = &drawable->Base;
921 
922     frontrb =
923 	dri_swrast_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
924     backrb =
925 	dri_swrast_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
926 
927     /* check for signle-buffered */
928     if (backrb == NULL)
929        return;
930 
931     iy = frontrb->Base.Base.Height - y - h;
932     data = (char *)backrb->Base.Buffer + (iy * backrb->pitch) + (x * ((backrb->bpp + 7) / 8));
933     sPriv->swrast_loader->putImage2(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP,
934                                     x, iy, w, h,
935                                     frontrb->pitch,
936                                     data,
937                                     dPriv->loaderPrivate);
938 }
939 
940 
941 static const struct __DriverAPIRec swrast_driver_api = {
942     .InitScreen = dri_init_screen,
943     .DestroyScreen = dri_destroy_screen,
944     .CreateContext = dri_create_context,
945     .DestroyContext = dri_destroy_context,
946     .CreateBuffer = dri_create_buffer,
947     .DestroyBuffer = dri_destroy_buffer,
948     .SwapBuffers = dri_swap_buffers,
949     .MakeCurrent = dri_make_current,
950     .UnbindContext = dri_unbind_context,
951     .CopySubBuffer = dri_copy_sub_buffer,
952 };
953 
954 static const struct __DRIDriverVtableExtensionRec swrast_vtable = {
955    .base = { __DRI_DRIVER_VTABLE, 1 },
956    .vtable = &swrast_driver_api,
957 };
958 
959 static const __DRIextension *swrast_driver_extensions[] = {
960     &driCoreExtension.base,
961     &driSWRastExtension.base,
962     &driCopySubBufferExtension.base,
963     &dri2ConfigQueryExtension.base,
964     &swrast_vtable.base,
965     NULL
966 };
967 
__driDriverGetExtensions_swrast(void)968 PUBLIC const __DRIextension **__driDriverGetExtensions_swrast(void)
969 {
970    globalDriverAPI = &swrast_driver_api;
971 
972    return swrast_driver_extensions;
973 }
974