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