2622935af930d47e5749cf30118d87039e47d1e1
[mesa.git] / src / mesa / drivers / dri / swrast / swrast.c
1 /*
2 * Copyright (C) 2008 George Sapountzis <gsap7@yahoo.gr>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 */
21
22 #include <GL/gl.h>
23 #include <GL/internal/dri_interface.h>
24 #include "context.h"
25 #include "extensions.h"
26 #include "framebuffer.h"
27 #include "imports.h"
28 #include "renderbuffer.h"
29 #include "swrast/swrast.h"
30 #include "swrast_setup/swrast_setup.h"
31 #include "tnl/tnl.h"
32 #include "tnl/t_context.h"
33 #include "tnl/t_pipeline.h"
34 #include "vbo/vbo.h"
35 #include "drivers/common/driverfuncs.h"
36
37 #include "swrast_priv.h"
38
39
40 #define need_GL_VERSION_1_3
41 #define need_GL_VERSION_1_4
42 #define need_GL_VERSION_1_5
43 #define need_GL_VERSION_2_0
44
45 /* sw extensions for imaging */
46 #define need_GL_EXT_blend_color
47 #define need_GL_EXT_blend_minmax
48 #define need_GL_EXT_convolution
49 #define need_GL_EXT_histogram
50 #define need_GL_SGI_color_table
51
52 /* sw extensions not associated with some GL version */
53 #define need_GL_ARB_shader_objects
54 #define need_GL_ARB_vertex_program
55 #define need_GL_APPLE_vertex_array_object
56 #define need_GL_ATI_fragment_shader
57 #define need_GL_EXT_depth_bounds_test
58 #define need_GL_EXT_framebuffer_object
59 #define need_GL_EXT_framebuffer_blit
60 #define need_GL_EXT_gpu_program_parameters
61 #define need_GL_EXT_paletted_texture
62 #define need_GL_IBM_multimode_draw_arrays
63 #define need_GL_MESA_resize_buffers
64 #define need_GL_NV_vertex_program
65 #define need_GL_NV_fragment_program
66
67 #include "extension_helper.h"
68 #include "utils.h"
69
70 const struct dri_extension card_extensions[] =
71 {
72 { "GL_VERSION_1_3", GL_VERSION_1_3_functions },
73 { "GL_VERSION_1_4", GL_VERSION_1_4_functions },
74 { "GL_VERSION_1_5", GL_VERSION_1_5_functions },
75 { "GL_VERSION_2_0", GL_VERSION_2_0_functions },
76
77 { "GL_EXT_blend_color", GL_EXT_blend_color_functions },
78 { "GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions },
79 { "GL_EXT_convolution", GL_EXT_convolution_functions },
80 { "GL_EXT_histogram", GL_EXT_histogram_functions },
81 { "GL_SGI_color_table", GL_SGI_color_table_functions },
82
83 { "GL_ARB_shader_objects", GL_ARB_shader_objects_functions },
84 { "GL_ARB_vertex_program", GL_ARB_vertex_program_functions },
85 { "GL_APPLE_vertex_array_object", GL_APPLE_vertex_array_object_functions },
86 { "GL_ATI_fragment_shader", GL_ATI_fragment_shader_functions },
87 { "GL_EXT_depth_bounds_test", GL_EXT_depth_bounds_test_functions },
88 { "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions },
89 { "GL_EXT_framebuffer_blit", GL_EXT_framebuffer_blit_functions },
90 { "GL_EXT_gpu_program_parameters", GL_EXT_gpu_program_parameters_functions },
91 { "GL_EXT_paletted_texture", GL_EXT_paletted_texture_functions },
92 { "GL_IBM_multimode_draw_arrays", GL_IBM_multimode_draw_arrays_functions },
93 { "GL_MESA_resize_buffers", GL_MESA_resize_buffers_functions },
94 { "GL_NV_vertex_program", GL_NV_vertex_program_functions },
95 { "GL_NV_fragment_program", GL_NV_fragment_program_functions },
96 { NULL, NULL }
97 };
98
99 static void
100 setupLoaderExtensions(__DRIscreen *psp,
101 const __DRIextension **extensions)
102 {
103 int i;
104
105 for (i = 0; extensions[i]; i++) {
106 if (strcmp(extensions[i]->name, __DRI_SWRAST_LOADER) == 0)
107 psp->swrast_loader = (__DRIswrastLoaderExtension *) extensions[i];
108 }
109 }
110
111 static __DRIconfig **
112 swrastFillInModes(__DRIscreen *psp,
113 unsigned pixel_bits, unsigned depth_bits,
114 unsigned stencil_bits, GLboolean have_back_buffer)
115 {
116 __DRIconfig **configs;
117 unsigned depth_buffer_factor;
118 unsigned back_buffer_factor;
119 GLenum fb_format;
120 GLenum fb_type;
121
122 /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
123 * support pageflipping at all.
124 */
125 static const GLenum back_buffer_modes[] = {
126 GLX_NONE, GLX_SWAP_UNDEFINED_OML
127 };
128
129 u_int8_t depth_bits_array[4];
130 u_int8_t stencil_bits_array[4];
131
132 depth_bits_array[0] = 0;
133 depth_bits_array[1] = 0;
134 depth_bits_array[2] = depth_bits;
135 depth_bits_array[3] = depth_bits;
136
137 /* Just like with the accumulation buffer, always provide some modes
138 * with a stencil buffer.
139 */
140 stencil_bits_array[0] = 0;
141 stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
142 stencil_bits_array[2] = 0;
143 stencil_bits_array[3] = (stencil_bits == 0) ? 8 : stencil_bits;
144
145 depth_buffer_factor = 4;
146 back_buffer_factor = 2;
147
148 if (pixel_bits == 16) {
149 fb_format = GL_RGB;
150 fb_type = GL_UNSIGNED_SHORT_5_6_5;
151 }
152 else {
153 fb_format = GL_BGRA;
154 fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
155 }
156
157 configs = driCreateConfigs(fb_format, fb_type,
158 depth_bits_array, stencil_bits_array,
159 depth_buffer_factor, back_buffer_modes,
160 back_buffer_factor);
161 if (configs == NULL) {
162 fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
163 __LINE__);
164 return NULL;
165 }
166
167 return configs;
168 }
169
170 static __DRIscreen *
171 driCreateNewScreen(int scrn, const __DRIextension **extensions,
172 const __DRIconfig ***driver_configs, void *data)
173 {
174 static const __DRIextension *emptyExtensionList[] = { NULL };
175 __DRIscreen *psp;
176
177 (void) data;
178
179 TRACE;
180
181 psp = _mesa_calloc(sizeof(*psp));
182 if (!psp)
183 return NULL;
184
185 setupLoaderExtensions(psp, extensions);
186
187 psp->num = scrn;
188 psp->extensions = emptyExtensionList;
189
190 *driver_configs = driConcatConfigs(swrastFillInModes(psp, 16, 16, 0, 1),
191 swrastFillInModes(psp, 32, 24, 8, 1));
192
193 driInitExtensions( NULL, card_extensions, GL_FALSE );
194
195 return psp;
196 }
197
198 static void driDestroyScreen(__DRIscreen *psp)
199 {
200 TRACE;
201
202 if (psp) {
203 _mesa_free(psp);
204 }
205 }
206
207 static const __DRIextension **driGetExtensions(__DRIscreen *psp)
208 {
209 TRACE;
210
211 return psp->extensions;
212 }
213
214
215 /**
216 * swrast_buffer.c
217 */
218
219 static GLuint
220 choose_pixel_format(const GLvisual *v)
221 {
222 if (v->rgbMode) {
223 /* XXX 24bpp packed, 8bpp, xmesa gets bitsPerPixel from xserver */
224 int bpp = v->rgbBits;
225 if (bpp == 24)
226 bpp = 32;
227
228 if (bpp == 32
229 && v->redMask == 0xff0000
230 && v->greenMask == 0x00ff00
231 && v->blueMask == 0x0000ff)
232 return PF_A8R8G8B8;
233 else if (bpp == 16
234 && v->redMask == 0xf800
235 && v->greenMask == 0x07e0
236 && v->blueMask == 0x001f)
237 return PF_R5G6B5;
238 }
239 else {
240 if (v->indexBits == 8)
241 return PF_CI8;
242 }
243
244 _mesa_problem( NULL, "unexpected format in %s", __FUNCTION__ );
245 return 0;
246 }
247
248 static void
249 swrast_delete_renderbuffer(struct gl_renderbuffer *rb)
250 {
251 TRACE;
252
253 _mesa_free(rb->Data);
254 _mesa_free(rb);
255 }
256
257 static GLboolean
258 swrast_alloc_front_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
259 GLenum internalFormat, GLuint width, GLuint height)
260 {
261 struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
262 int bpp;
263
264 TRACE;
265
266 rb->Data = NULL;
267 rb->Width = width;
268 rb->Height = height;
269
270 switch (internalFormat) {
271 case GL_RGB:
272 bpp = rb->RedBits + rb->GreenBits + rb->BlueBits;
273 break;
274 case GL_RGBA:
275 bpp = rb->RedBits + rb->GreenBits + rb->BlueBits + rb->AlphaBits;
276 break;
277 case GL_COLOR_INDEX8_EXT:
278 bpp = rb->IndexBits;
279 break;
280 default:
281 _mesa_problem( NULL, "unexpected format in %s", __FUNCTION__ );
282 return GL_FALSE;
283 }
284
285 /* always pad to 32 bits */
286 xrb->pitch = ((width * bpp + 0x1f) & ~0x1f) / 8;
287
288 return GL_TRUE;
289 }
290
291 static GLboolean
292 swrast_alloc_back_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
293 GLenum internalFormat, GLuint width, GLuint height)
294 {
295 struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb);
296
297 TRACE;
298
299 _mesa_free(rb->Data);
300
301 (void) swrast_alloc_front_storage(ctx, rb, internalFormat, width, height);
302
303 rb->Data = _mesa_malloc(height * xrb->pitch);
304
305 return GL_TRUE;
306 }
307
308 static struct swrast_renderbuffer *
309 swrast_new_renderbuffer(const GLvisual *visual, GLboolean front)
310 {
311 struct swrast_renderbuffer *xrb = _mesa_calloc(sizeof *xrb);
312 GLuint pixel_format;
313
314 TRACE;
315
316 if (xrb) {
317 _mesa_init_renderbuffer(&xrb->Base, 0);
318
319 pixel_format = choose_pixel_format(visual);
320
321 xrb->Base.Delete = swrast_delete_renderbuffer;
322 if (front) {
323 xrb->Base.AllocStorage = swrast_alloc_front_storage;
324 swrast_set_span_funcs_pixmap(xrb, pixel_format);
325 }
326 else {
327 xrb->Base.AllocStorage = swrast_alloc_back_storage;
328 swrast_set_span_funcs_ximage(xrb, pixel_format);
329 }
330
331 switch (pixel_format) {
332 case PF_A8R8G8B8:
333 xrb->Base.InternalFormat = GL_RGBA;
334 xrb->Base._BaseFormat = GL_RGBA;
335 xrb->Base.DataType = GL_UNSIGNED_BYTE;
336 xrb->Base.RedBits = 8 * sizeof(GLubyte);
337 xrb->Base.GreenBits = 8 * sizeof(GLubyte);
338 xrb->Base.BlueBits = 8 * sizeof(GLubyte);
339 xrb->Base.AlphaBits = 8 * sizeof(GLubyte);
340 break;
341 case PF_R5G6B5:
342 xrb->Base.InternalFormat = GL_RGB;
343 xrb->Base._BaseFormat = GL_RGB;
344 xrb->Base.DataType = GL_UNSIGNED_BYTE;
345 xrb->Base.RedBits = 5 * sizeof(GLubyte);
346 xrb->Base.GreenBits = 6 * sizeof(GLubyte);
347 xrb->Base.BlueBits = 5 * sizeof(GLubyte);
348 xrb->Base.AlphaBits = 0;
349 break;
350 case PF_CI8:
351 xrb->Base.InternalFormat = GL_COLOR_INDEX8_EXT;
352 xrb->Base._BaseFormat = GL_COLOR_INDEX;
353 xrb->Base.DataType = GL_UNSIGNED_BYTE;
354 xrb->Base.IndexBits = 8 * sizeof(GLubyte);
355 break;
356 default:
357 return NULL;
358 }
359 }
360 return xrb;
361 }
362
363 static __DRIdrawable *
364 driCreateNewDrawable(__DRIscreen *screen,
365 const __DRIconfig *config, void *data)
366 {
367 __DRIdrawable *buf;
368 struct swrast_renderbuffer *frontrb, *backrb;
369
370 TRACE;
371
372 buf = _mesa_calloc(sizeof *buf);
373 if (!buf)
374 return NULL;
375
376 buf->loaderPrivate = data;
377
378 buf->driScreenPriv = screen;
379
380 buf->row = _mesa_malloc(MAX_WIDTH * 4);
381
382 /* basic framebuffer setup */
383 _mesa_initialize_framebuffer(&buf->Base, &config->modes);
384
385 /* add front renderbuffer */
386 frontrb = swrast_new_renderbuffer(&config->modes, GL_TRUE);
387 _mesa_add_renderbuffer(&buf->Base, BUFFER_FRONT_LEFT, &frontrb->Base);
388
389 /* add back renderbuffer */
390 if (config->modes.doubleBufferMode) {
391 backrb = swrast_new_renderbuffer(&config->modes, GL_FALSE);
392 _mesa_add_renderbuffer(&buf->Base, BUFFER_BACK_LEFT, &backrb->Base);
393 }
394
395 /* add software renderbuffers */
396 _mesa_add_soft_renderbuffers(&buf->Base,
397 GL_FALSE, /* color */
398 config->modes.haveDepthBuffer,
399 config->modes.haveStencilBuffer,
400 config->modes.haveAccumBuffer,
401 GL_FALSE, /* alpha */
402 GL_FALSE /* aux bufs */);
403
404 return buf;
405 }
406
407 static void
408 driDestroyDrawable(__DRIdrawable *buf)
409 {
410 TRACE;
411
412 if (buf) {
413 struct gl_framebuffer *fb = &buf->Base;
414
415 _mesa_free(buf->row);
416
417 fb->DeletePending = GL_TRUE;
418 _mesa_unreference_framebuffer(&fb);
419 }
420 }
421
422 static void driSwapBuffers(__DRIdrawable *buf)
423 {
424 GET_CURRENT_CONTEXT(ctx);
425
426 struct swrast_renderbuffer *frontrb =
427 swrast_renderbuffer(buf->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
428 struct swrast_renderbuffer *backrb =
429 swrast_renderbuffer(buf->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer);
430
431 __DRIscreen *screen = buf->driScreenPriv;
432
433 TRACE;
434
435 /* check for signle-buffered */
436 if (backrb == NULL)
437 return;
438
439 /* check if swapping currently bound buffer */
440 if (ctx && ctx->DrawBuffer == &(buf->Base)) {
441 /* flush pending rendering */
442 _mesa_notifySwapBuffers(ctx);
443 }
444
445 screen->swrast_loader->putImage(buf, __DRI_SWRAST_IMAGE_OP_SWAP,
446 0, 0,
447 frontrb->Base.Width,
448 frontrb->Base.Height,
449 backrb->Base.Data,
450 buf->loaderPrivate);
451 }
452
453
454 /**
455 * swrast_dd.c
456 */
457
458 static void
459 get_window_size( GLframebuffer *fb, GLsizei *w, GLsizei *h )
460 {
461 __DRIdrawable *buf = swrast_drawable(fb);
462 __DRIscreen *screen = buf->driScreenPriv;
463 int x, y;
464
465 screen->swrast_loader->getDrawableInfo(buf,
466 &x, &y, w, h,
467 buf->loaderPrivate);
468 }
469
470 static void
471 swrast_check_and_update_window_size( GLcontext *ctx, GLframebuffer *fb )
472 {
473 GLsizei width, height;
474
475 get_window_size(fb, &width, &height);
476 if (fb->Width != width || fb->Height != height) {
477 _mesa_resize_framebuffer(ctx, fb, width, height);
478 }
479 }
480
481 static const GLubyte *
482 get_string(GLcontext *ctx, GLenum pname)
483 {
484 (void) ctx;
485 switch (pname) {
486 case GL_VENDOR:
487 return (const GLubyte *) "Mesa Project";
488 case GL_RENDERER:
489 return (const GLubyte *) "X.Org";
490 default:
491 return NULL;
492 }
493 }
494
495 static void
496 update_state( GLcontext *ctx, GLuint new_state )
497 {
498 /* not much to do here - pass it on */
499 _swrast_InvalidateState( ctx, new_state );
500 _swsetup_InvalidateState( ctx, new_state );
501 _vbo_InvalidateState( ctx, new_state );
502 _tnl_InvalidateState( ctx, new_state );
503 }
504
505 static void
506 viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
507 {
508 GLframebuffer *draw = ctx->WinSysDrawBuffer;
509 GLframebuffer *read = ctx->WinSysReadBuffer;
510
511 swrast_check_and_update_window_size(ctx, draw);
512 swrast_check_and_update_window_size(ctx, read);
513 }
514
515 static void
516 swrast_init_driver_functions(struct dd_function_table *driver)
517 {
518 driver->GetString = get_string;
519 driver->UpdateState = update_state;
520 driver->GetBufferSize = NULL;
521 driver->Viewport = viewport;
522 }
523
524
525 /**
526 * swrast_context.c
527 */
528
529 static __DRIcontext *
530 driCreateNewContext(__DRIscreen *screen, const __DRIconfig *config,
531 __DRIcontext *shared, void *data)
532 {
533 __DRIcontext *ctx;
534 GLcontext *mesaCtx;
535 struct dd_function_table functions;
536
537 TRACE;
538
539 ctx = _mesa_calloc(sizeof *ctx);
540 if (!ctx)
541 return NULL;
542
543 ctx->loaderPrivate = data;
544
545 ctx->driScreenPriv = screen;
546
547 /* build table of device driver functions */
548 _mesa_init_driver_functions(&functions);
549 swrast_init_driver_functions(&functions);
550
551 if (!_mesa_initialize_context(&ctx->Base, &config->modes,
552 shared ? &shared->Base : NULL,
553 &functions, (void *) ctx)) {
554 _mesa_free(ctx);
555 return NULL;
556 }
557
558 mesaCtx = &ctx->Base;
559
560 /* do bounds checking to prevent segfaults and server crashes! */
561 mesaCtx->Const.CheckArrayBounds = GL_TRUE;
562
563 /* create module contexts */
564 _swrast_CreateContext( mesaCtx );
565 _vbo_CreateContext( mesaCtx );
566 _tnl_CreateContext( mesaCtx );
567 _swsetup_CreateContext( mesaCtx );
568 _swsetup_Wakeup( mesaCtx );
569
570 /* use default TCL pipeline */
571 {
572 TNLcontext *tnl = TNL_CONTEXT(mesaCtx);
573 tnl->Driver.RunPipeline = _tnl_run_pipeline;
574 }
575
576 _mesa_enable_sw_extensions(mesaCtx);
577 _mesa_enable_1_3_extensions(mesaCtx);
578 _mesa_enable_1_4_extensions(mesaCtx);
579 _mesa_enable_1_5_extensions(mesaCtx);
580 _mesa_enable_2_0_extensions(mesaCtx);
581 _mesa_enable_2_1_extensions(mesaCtx);
582
583 return ctx;
584 }
585
586 static void
587 driDestroyContext(__DRIcontext *ctx)
588 {
589 GLcontext *mesaCtx;
590 TRACE;
591
592 if (ctx) {
593 mesaCtx = &ctx->Base;
594 _swsetup_DestroyContext( mesaCtx );
595 _swrast_DestroyContext( mesaCtx );
596 _tnl_DestroyContext( mesaCtx );
597 _vbo_DestroyContext( mesaCtx );
598 _mesa_destroy_context( mesaCtx );
599 }
600 }
601
602 static int
603 driCopyContext(__DRIcontext *dst, __DRIcontext *src, unsigned long mask)
604 {
605 TRACE;
606
607 _mesa_copy_context(&src->Base, &dst->Base, mask);
608 return GL_TRUE;
609 }
610
611 static int driBindContext(__DRIcontext *ctx,
612 __DRIdrawable *draw,
613 __DRIdrawable *read)
614 {
615 GLcontext *mesaCtx;
616 GLframebuffer *mesaDraw;
617 GLframebuffer *mesaRead;
618 TRACE;
619
620 if (ctx) {
621 if (!draw || !read)
622 return GL_FALSE;
623
624 /* check for same context and buffer */
625 mesaCtx = &ctx->Base;
626 mesaDraw = &draw->Base;
627 mesaRead = &read->Base;
628 if (mesaCtx == _mesa_get_current_context()
629 && mesaCtx->DrawBuffer == mesaDraw
630 && mesaCtx->ReadBuffer == mesaRead) {
631 return GL_TRUE;
632 }
633
634 _glapi_check_multithread();
635
636 swrast_check_and_update_window_size(mesaCtx, mesaDraw);
637 if (read != draw)
638 swrast_check_and_update_window_size(mesaCtx, mesaRead);
639
640 _mesa_make_current( mesaCtx,
641 mesaDraw,
642 mesaRead );
643 }
644 else {
645 /* unbind */
646 _mesa_make_current( NULL, NULL, NULL );
647 }
648
649 return GL_TRUE;
650 }
651
652 static int driUnbindContext(__DRIcontext *ctx)
653 {
654 TRACE;
655 (void) ctx;
656 _mesa_make_current(NULL, NULL, NULL);
657 return GL_TRUE;
658 }
659
660
661 static const __DRIcoreExtension driCoreExtension = {
662 { __DRI_CORE, __DRI_CORE_VERSION },
663 NULL,
664 driDestroyScreen,
665 driGetExtensions,
666 driGetConfigAttrib,
667 driIndexConfigAttrib,
668 NULL,
669 driDestroyDrawable,
670 driSwapBuffers,
671 driCreateNewContext,
672 driCopyContext,
673 driDestroyContext,
674 driBindContext,
675 driUnbindContext
676 };
677
678 static const __DRIswrastExtension driSWRastExtension = {
679 { __DRI_SWRAST, __DRI_SWRAST_VERSION },
680 driCreateNewScreen,
681 driCreateNewDrawable,
682 };
683
684 /* This is the table of extensions that the loader will dlsym() for. */
685 PUBLIC const __DRIextension *__driDriverExtensions[] = {
686 &driCoreExtension.base,
687 &driSWRastExtension.base,
688 NULL
689 };