2 * Copyright (C) 2008 George Sapountzis <gsap7@yahoo.gr>
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:
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
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.
23 #include <GL/internal/dri_interface.h>
25 #include "extensions.h"
26 #include "framebuffer.h"
28 #include "renderbuffer.h"
29 #include "swrast/swrast.h"
30 #include "swrast_setup/swrast_setup.h"
32 #include "tnl/t_context.h"
33 #include "tnl/t_pipeline.h"
35 #include "drivers/common/driverfuncs.h"
37 #include "swrast_priv.h"
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
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
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
67 #include "extension_helper.h"
70 const struct dri_extension card_extensions
[] =
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
},
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
},
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
},
100 setupLoaderExtensions(__DRIscreen
*psp
,
101 const __DRIextension
**extensions
)
105 for (i
= 0; extensions
[i
]; i
++) {
106 if (strcmp(extensions
[i
]->name
, __DRI_SWRAST_LOADER
) == 0)
107 psp
->swrast_loader
= (__DRIswrastLoaderExtension
*) extensions
[i
];
111 static __DRIconfig
**
112 swrastFillInModes(__DRIscreen
*psp
,
113 unsigned pixel_bits
, unsigned depth_bits
,
114 unsigned stencil_bits
, GLboolean have_back_buffer
)
116 __DRIconfig
**configs
;
117 unsigned depth_buffer_factor
;
118 unsigned back_buffer_factor
;
122 /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
123 * support pageflipping at all.
125 static const GLenum back_buffer_modes
[] = {
126 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
129 u_int8_t depth_bits_array
[4];
130 u_int8_t stencil_bits_array
[4];
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
;
137 /* Just like with the accumulation buffer, always provide some modes
138 * with a stencil buffer.
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
;
145 depth_buffer_factor
= 4;
146 back_buffer_factor
= 2;
148 if (pixel_bits
== 16) {
150 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
154 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
157 configs
= driCreateConfigs(fb_format
, fb_type
,
158 depth_bits_array
, stencil_bits_array
,
159 depth_buffer_factor
, back_buffer_modes
,
161 if (configs
== NULL
) {
162 fprintf(stderr
, "[%s:%u] Error creating FBConfig!\n", __func__
,
171 driCreateNewScreen(int scrn
, const __DRIextension
**extensions
,
172 const __DRIconfig
***driver_configs
, void *data
)
174 static const __DRIextension
*emptyExtensionList
[] = { NULL
};
181 psp
= _mesa_calloc(sizeof(*psp
));
185 setupLoaderExtensions(psp
, extensions
);
188 psp
->extensions
= emptyExtensionList
;
190 *driver_configs
= driConcatConfigs(swrastFillInModes(psp
, 16, 16, 0, 1),
191 swrastFillInModes(psp
, 32, 24, 8, 1));
193 driInitExtensions( NULL
, card_extensions
, GL_FALSE
);
198 static void driDestroyScreen(__DRIscreen
*psp
)
207 static const __DRIextension
**driGetExtensions(__DRIscreen
*psp
)
211 return psp
->extensions
;
220 choose_pixel_format(const GLvisual
*v
)
223 /* XXX 24bpp packed, 8bpp, xmesa gets bitsPerPixel from xserver */
224 int bpp
= v
->rgbBits
;
229 && v
->redMask
== 0xff0000
230 && v
->greenMask
== 0x00ff00
231 && v
->blueMask
== 0x0000ff)
234 && v
->redMask
== 0xf800
235 && v
->greenMask
== 0x07e0
236 && v
->blueMask
== 0x001f)
240 if (v
->indexBits
== 8)
244 _mesa_problem( NULL
, "unexpected format in %s", __FUNCTION__
);
249 swrast_delete_renderbuffer(struct gl_renderbuffer
*rb
)
253 _mesa_free(rb
->Data
);
258 swrast_alloc_front_storage(GLcontext
*ctx
, struct gl_renderbuffer
*rb
,
259 GLenum internalFormat
, GLuint width
, GLuint height
)
261 struct swrast_renderbuffer
*xrb
= swrast_renderbuffer(rb
);
270 switch (internalFormat
) {
272 bpp
= rb
->RedBits
+ rb
->GreenBits
+ rb
->BlueBits
;
275 bpp
= rb
->RedBits
+ rb
->GreenBits
+ rb
->BlueBits
+ rb
->AlphaBits
;
277 case GL_COLOR_INDEX8_EXT
:
281 _mesa_problem( NULL
, "unexpected format in %s", __FUNCTION__
);
285 /* always pad to 32 bits */
286 xrb
->pitch
= ((width
* bpp
+ 0x1f) & ~0x1f) / 8;
292 swrast_alloc_back_storage(GLcontext
*ctx
, struct gl_renderbuffer
*rb
,
293 GLenum internalFormat
, GLuint width
, GLuint height
)
295 struct swrast_renderbuffer
*xrb
= swrast_renderbuffer(rb
);
299 _mesa_free(rb
->Data
);
301 (void) swrast_alloc_front_storage(ctx
, rb
, internalFormat
, width
, height
);
303 rb
->Data
= _mesa_malloc(height
* xrb
->pitch
);
308 static struct swrast_renderbuffer
*
309 swrast_new_renderbuffer(const GLvisual
*visual
, GLboolean front
)
311 struct swrast_renderbuffer
*xrb
= _mesa_calloc(sizeof *xrb
);
317 _mesa_init_renderbuffer(&xrb
->Base
, 0);
319 pixel_format
= choose_pixel_format(visual
);
321 xrb
->Base
.Delete
= swrast_delete_renderbuffer
;
323 xrb
->Base
.AllocStorage
= swrast_alloc_front_storage
;
324 swrast_set_span_funcs_pixmap(xrb
, pixel_format
);
327 xrb
->Base
.AllocStorage
= swrast_alloc_back_storage
;
328 swrast_set_span_funcs_ximage(xrb
, pixel_format
);
331 switch (pixel_format
) {
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
);
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;
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
);
363 static __DRIdrawable
*
364 driCreateNewDrawable(__DRIscreen
*screen
,
365 const __DRIconfig
*config
, void *data
)
368 struct swrast_renderbuffer
*frontrb
, *backrb
;
372 buf
= _mesa_calloc(sizeof *buf
);
376 buf
->loaderPrivate
= data
;
378 buf
->driScreenPriv
= screen
;
380 buf
->row
= _mesa_malloc(MAX_WIDTH
* 4);
382 /* basic framebuffer setup */
383 _mesa_initialize_framebuffer(&buf
->Base
, &config
->modes
);
385 /* add front renderbuffer */
386 frontrb
= swrast_new_renderbuffer(&config
->modes
, GL_TRUE
);
387 _mesa_add_renderbuffer(&buf
->Base
, BUFFER_FRONT_LEFT
, &frontrb
->Base
);
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
);
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 */);
408 driDestroyDrawable(__DRIdrawable
*buf
)
413 struct gl_framebuffer
*fb
= &buf
->Base
;
415 _mesa_free(buf
->row
);
417 fb
->DeletePending
= GL_TRUE
;
418 _mesa_unreference_framebuffer(&fb
);
422 static void driSwapBuffers(__DRIdrawable
*buf
)
424 GET_CURRENT_CONTEXT(ctx
);
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
);
431 __DRIscreen
*screen
= buf
->driScreenPriv
;
435 /* check for signle-buffered */
439 /* check if swapping currently bound buffer */
440 if (ctx
&& ctx
->DrawBuffer
== &(buf
->Base
)) {
441 /* flush pending rendering */
442 _mesa_notifySwapBuffers(ctx
);
445 screen
->swrast_loader
->putImage(buf
, __DRI_SWRAST_IMAGE_OP_SWAP
,
448 frontrb
->Base
.Height
,
459 get_window_size( GLframebuffer
*fb
, GLsizei
*w
, GLsizei
*h
)
461 __DRIdrawable
*buf
= swrast_drawable(fb
);
462 __DRIscreen
*screen
= buf
->driScreenPriv
;
465 screen
->swrast_loader
->getDrawableInfo(buf
,
471 swrast_check_and_update_window_size( GLcontext
*ctx
, GLframebuffer
*fb
)
473 GLsizei width
, height
;
475 get_window_size(fb
, &width
, &height
);
476 if (fb
->Width
!= width
|| fb
->Height
!= height
) {
477 _mesa_resize_framebuffer(ctx
, fb
, width
, height
);
481 static const GLubyte
*
482 get_string(GLcontext
*ctx
, GLenum pname
)
487 return (const GLubyte
*) "Mesa Project";
489 return (const GLubyte
*) "X.Org";
496 update_state( GLcontext
*ctx
, GLuint new_state
)
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
);
506 viewport(GLcontext
*ctx
, GLint x
, GLint y
, GLsizei w
, GLsizei h
)
508 GLframebuffer
*draw
= ctx
->WinSysDrawBuffer
;
509 GLframebuffer
*read
= ctx
->WinSysReadBuffer
;
511 swrast_check_and_update_window_size(ctx
, draw
);
512 swrast_check_and_update_window_size(ctx
, read
);
516 swrast_init_driver_functions(struct dd_function_table
*driver
)
518 driver
->GetString
= get_string
;
519 driver
->UpdateState
= update_state
;
520 driver
->GetBufferSize
= NULL
;
521 driver
->Viewport
= viewport
;
529 static __DRIcontext
*
530 driCreateNewContext(__DRIscreen
*screen
, const __DRIconfig
*config
,
531 __DRIcontext
*shared
, void *data
)
535 struct dd_function_table functions
;
539 ctx
= _mesa_calloc(sizeof *ctx
);
543 ctx
->loaderPrivate
= data
;
545 ctx
->driScreenPriv
= screen
;
547 /* build table of device driver functions */
548 _mesa_init_driver_functions(&functions
);
549 swrast_init_driver_functions(&functions
);
551 if (!_mesa_initialize_context(&ctx
->Base
, &config
->modes
,
552 shared
? &shared
->Base
: NULL
,
553 &functions
, (void *) ctx
)) {
558 mesaCtx
= &ctx
->Base
;
560 /* do bounds checking to prevent segfaults and server crashes! */
561 mesaCtx
->Const
.CheckArrayBounds
= GL_TRUE
;
563 /* create module contexts */
564 _swrast_CreateContext( mesaCtx
);
565 _vbo_CreateContext( mesaCtx
);
566 _tnl_CreateContext( mesaCtx
);
567 _swsetup_CreateContext( mesaCtx
);
568 _swsetup_Wakeup( mesaCtx
);
570 /* use default TCL pipeline */
572 TNLcontext
*tnl
= TNL_CONTEXT(mesaCtx
);
573 tnl
->Driver
.RunPipeline
= _tnl_run_pipeline
;
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
);
587 driDestroyContext(__DRIcontext
*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
);
603 driCopyContext(__DRIcontext
*dst
, __DRIcontext
*src
, unsigned long mask
)
607 _mesa_copy_context(&src
->Base
, &dst
->Base
, mask
);
611 static int driBindContext(__DRIcontext
*ctx
,
616 GLframebuffer
*mesaDraw
;
617 GLframebuffer
*mesaRead
;
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
) {
634 _glapi_check_multithread();
636 swrast_check_and_update_window_size(mesaCtx
, mesaDraw
);
638 swrast_check_and_update_window_size(mesaCtx
, mesaRead
);
640 _mesa_make_current( mesaCtx
,
646 _mesa_make_current( NULL
, NULL
, NULL
);
652 static int driUnbindContext(__DRIcontext
*ctx
)
656 _mesa_make_current(NULL
, NULL
, NULL
);
661 static const __DRIcoreExtension driCoreExtension
= {
662 { __DRI_CORE
, __DRI_CORE_VERSION
},
667 driIndexConfigAttrib
,
678 static const __DRIswrastExtension driSWRastExtension
= {
679 { __DRI_SWRAST
, __DRI_SWRAST_VERSION
},
681 driCreateNewDrawable
,
684 /* This is the table of extensions that the loader will dlsym() for. */
685 PUBLIC
const __DRIextension
*__driDriverExtensions
[] = {
686 &driCoreExtension
.base
,
687 &driSWRastExtension
.base
,