| /* |
| * Copyright (C) 2008 George Sapountzis <gsap7@yahoo.gr> |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
| * to deal in the Software without restriction, including without limitation |
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| * and/or sell copies of the Software, and to permit persons to whom the |
| * Software is furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be included |
| * in all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
| * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| */ |
| |
| /* |
| * DRI software rasterizer |
| * |
| * This is the mesa swrast module packaged into a DRI driver structure. |
| * |
| * The front-buffer is allocated by the loader. The loader provides read/write |
| * callbacks for access to the front-buffer. The driver uses a scratch row for |
| * front-buffer rendering to avoid repeated calls to the loader. |
| * |
| * The back-buffer is allocated by the driver and is private. |
| */ |
| |
| #include "context.h" |
| #include "extensions.h" |
| #include "framebuffer.h" |
| #include "imports.h" |
| #include "renderbuffer.h" |
| #include "swrast/swrast.h" |
| #include "swrast_setup/swrast_setup.h" |
| #include "tnl/tnl.h" |
| #include "tnl/t_context.h" |
| #include "tnl/t_pipeline.h" |
| #include "vbo/vbo.h" |
| #include "drivers/common/driverfuncs.h" |
| #include "utils.h" |
| |
| #include "swrast_priv.h" |
| |
| |
| #define need_GL_VERSION_1_3 |
| #define need_GL_VERSION_1_4 |
| #define need_GL_VERSION_1_5 |
| #define need_GL_VERSION_2_0 |
| #define need_GL_VERSION_2_1 |
| |
| /* sw extensions for imaging */ |
| #define need_GL_EXT_blend_color |
| #define need_GL_EXT_blend_minmax |
| #define need_GL_EXT_convolution |
| #define need_GL_EXT_histogram |
| #define need_GL_SGI_color_table |
| |
| /* sw extensions not associated with some GL version */ |
| #define need_GL_ARB_shader_objects |
| #define need_GL_ARB_vertex_program |
| #define need_GL_APPLE_vertex_array_object |
| #define need_GL_ATI_fragment_shader |
| #define need_GL_EXT_depth_bounds_test |
| #define need_GL_EXT_framebuffer_object |
| #define need_GL_EXT_framebuffer_blit |
| #define need_GL_EXT_gpu_program_parameters |
| #define need_GL_EXT_paletted_texture |
| #define need_GL_IBM_multimode_draw_arrays |
| #define need_GL_MESA_resize_buffers |
| #define need_GL_NV_vertex_program |
| #define need_GL_NV_fragment_program |
| |
| #include "extension_helper.h" |
| |
| const struct dri_extension card_extensions[] = |
| { |
| { "GL_VERSION_1_3", GL_VERSION_1_3_functions }, |
| { "GL_VERSION_1_4", GL_VERSION_1_4_functions }, |
| { "GL_VERSION_1_5", GL_VERSION_1_5_functions }, |
| { "GL_VERSION_2_0", GL_VERSION_2_0_functions }, |
| { "GL_VERSION_2_1", GL_VERSION_2_1_functions }, |
| |
| { "GL_EXT_blend_color", GL_EXT_blend_color_functions }, |
| { "GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions }, |
| { "GL_EXT_convolution", GL_EXT_convolution_functions }, |
| { "GL_EXT_histogram", GL_EXT_histogram_functions }, |
| { "GL_SGI_color_table", GL_SGI_color_table_functions }, |
| |
| { "GL_ARB_shader_objects", GL_ARB_shader_objects_functions }, |
| { "GL_ARB_vertex_program", GL_ARB_vertex_program_functions }, |
| { "GL_APPLE_vertex_array_object", GL_APPLE_vertex_array_object_functions }, |
| { "GL_ATI_fragment_shader", GL_ATI_fragment_shader_functions }, |
| { "GL_EXT_depth_bounds_test", GL_EXT_depth_bounds_test_functions }, |
| { "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions }, |
| { "GL_EXT_framebuffer_blit", GL_EXT_framebuffer_blit_functions }, |
| { "GL_EXT_gpu_program_parameters", GL_EXT_gpu_program_parameters_functions }, |
| { "GL_EXT_paletted_texture", GL_EXT_paletted_texture_functions }, |
| { "GL_IBM_multimode_draw_arrays", GL_IBM_multimode_draw_arrays_functions }, |
| { "GL_MESA_resize_buffers", GL_MESA_resize_buffers_functions }, |
| { "GL_NV_vertex_program", GL_NV_vertex_program_functions }, |
| { "GL_NV_fragment_program", GL_NV_fragment_program_functions }, |
| { NULL, NULL } |
| }; |
| |
| |
| /** |
| * Screen and config-related functions |
| */ |
| |
| static void |
| setupLoaderExtensions(__DRIscreen *psp, |
| const __DRIextension **extensions) |
| { |
| int i; |
| |
| for (i = 0; extensions[i]; i++) { |
| if (strcmp(extensions[i]->name, __DRI_SWRAST_LOADER) == 0) |
| psp->swrast_loader = (__DRIswrastLoaderExtension *) extensions[i]; |
| } |
| } |
| |
| static __DRIconfig ** |
| swrastFillInModes(__DRIscreen *psp, |
| unsigned pixel_bits, unsigned depth_bits, |
| unsigned stencil_bits, GLboolean have_back_buffer) |
| { |
| __DRIconfig **configs; |
| unsigned depth_buffer_factor; |
| unsigned back_buffer_factor; |
| GLenum fb_format; |
| GLenum fb_type; |
| |
| /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't |
| * support pageflipping at all. |
| */ |
| static const GLenum back_buffer_modes[] = { |
| GLX_NONE, GLX_SWAP_UNDEFINED_OML |
| }; |
| |
| u_int8_t depth_bits_array[4]; |
| u_int8_t stencil_bits_array[4]; |
| |
| depth_bits_array[0] = 0; |
| depth_bits_array[1] = 0; |
| depth_bits_array[2] = depth_bits; |
| depth_bits_array[3] = depth_bits; |
| |
| /* Just like with the accumulation buffer, always provide some modes |
| * with a stencil buffer. |
| */ |
| stencil_bits_array[0] = 0; |
| stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits; |
| stencil_bits_array[2] = 0; |
| stencil_bits_array[3] = (stencil_bits == 0) ? 8 : stencil_bits; |
| |
| depth_buffer_factor = 4; |
| back_buffer_factor = 2; |
| |
| if (pixel_bits == 8) { |
| fb_format = GL_RGB; |
| fb_type = GL_UNSIGNED_BYTE_2_3_3_REV; |
| } |
| else if (pixel_bits == 16) { |
| fb_format = GL_RGB; |
| fb_type = GL_UNSIGNED_SHORT_5_6_5; |
| } |
| else { |
| fb_format = GL_BGRA; |
| fb_type = GL_UNSIGNED_INT_8_8_8_8_REV; |
| } |
| |
| configs = driCreateConfigs(fb_format, fb_type, |
| depth_bits_array, stencil_bits_array, |
| depth_buffer_factor, back_buffer_modes, |
| back_buffer_factor); |
| if (configs == NULL) { |
| fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__, |
| __LINE__); |
| return NULL; |
| } |
| |
| return configs; |
| } |
| |
| static __DRIscreen * |
| driCreateNewScreen(int scrn, const __DRIextension **extensions, |
| const __DRIconfig ***driver_configs, void *data) |
| { |
| static const __DRIextension *emptyExtensionList[] = { NULL }; |
| __DRIscreen *psp; |
| __DRIconfig **configs8, **configs16, **configs32; |
| |
| (void) data; |
| |
| TRACE; |
| |
| psp = _mesa_calloc(sizeof(*psp)); |
| if (!psp) |
| return NULL; |
| |
| setupLoaderExtensions(psp, extensions); |
| |
| psp->num = scrn; |
| psp->extensions = emptyExtensionList; |
| |
| configs8 = swrastFillInModes(psp, 8, 8, 0, 1); |
| configs16 = swrastFillInModes(psp, 16, 16, 0, 1); |
| configs32 = swrastFillInModes(psp, 32, 24, 8, 1); |
| |
| configs16 = (__DRIconfig **)driConcatConfigs(configs8, configs16); |
| |
| *driver_configs = driConcatConfigs(configs16, configs32); |
| |
| driInitExtensions( NULL, card_extensions, GL_FALSE ); |
| |
| return psp; |
| } |
| |
| static void driDestroyScreen(__DRIscreen *psp) |
| { |
| TRACE; |
| |
| if (psp) { |
| _mesa_free(psp); |
| } |
| } |
| |
| static const __DRIextension **driGetExtensions(__DRIscreen *psp) |
| { |
| TRACE; |
| |
| return psp->extensions; |
| } |
| |
| |
| /** |
| * Framebuffer and renderbuffer-related functions. |
| */ |
| |
| static GLuint |
| choose_pixel_format(const GLvisual *v) |
| { |
| if (v->rgbMode) { |
| int bpp = v->rgbBits; |
| |
| if (bpp == 32 |
| && v->redMask == 0xff0000 |
| && v->greenMask == 0x00ff00 |
| && v->blueMask == 0x0000ff) |
| return PF_A8R8G8B8; |
| else if (bpp == 16 |
| && v->redMask == 0xf800 |
| && v->greenMask == 0x07e0 |
| && v->blueMask == 0x001f) |
| return PF_R5G6B5; |
| else if (bpp == 8 |
| && v->redMask == 0x07 |
| && v->greenMask == 0x38 |
| && v->blueMask == 0xc0) |
| return PF_R3G3B2; |
| } |
| else { |
| if (v->indexBits == 8) |
| return PF_CI8; |
| } |
| |
| _mesa_problem( NULL, "unexpected format in %s", __FUNCTION__ ); |
| return 0; |
| } |
| |
| static void |
| swrast_delete_renderbuffer(struct gl_renderbuffer *rb) |
| { |
| TRACE; |
| |
| _mesa_free(rb->Data); |
| _mesa_free(rb); |
| } |
| |
| static GLboolean |
| swrast_alloc_front_storage(GLcontext *ctx, struct gl_renderbuffer *rb, |
| GLenum internalFormat, GLuint width, GLuint height) |
| { |
| struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb); |
| int bpp; |
| unsigned mask = PITCH_ALIGN_BITS - 1; |
| |
| TRACE; |
| |
| rb->Data = NULL; |
| rb->Width = width; |
| rb->Height = height; |
| |
| switch (internalFormat) { |
| case GL_RGB: |
| bpp = rb->RedBits + rb->GreenBits + rb->BlueBits; |
| break; |
| case GL_RGBA: |
| bpp = rb->RedBits + rb->GreenBits + rb->BlueBits + rb->AlphaBits; |
| break; |
| case GL_COLOR_INDEX8_EXT: |
| bpp = rb->IndexBits; |
| break; |
| default: |
| _mesa_problem( NULL, "unexpected format in %s", __FUNCTION__ ); |
| return GL_FALSE; |
| } |
| |
| /* always pad to PITCH_ALIGN_BITS */ |
| xrb->pitch = ((width * bpp + mask) & ~mask) / 8; |
| |
| return GL_TRUE; |
| } |
| |
| static GLboolean |
| swrast_alloc_back_storage(GLcontext *ctx, struct gl_renderbuffer *rb, |
| GLenum internalFormat, GLuint width, GLuint height) |
| { |
| struct swrast_renderbuffer *xrb = swrast_renderbuffer(rb); |
| |
| TRACE; |
| |
| _mesa_free(rb->Data); |
| |
| swrast_alloc_front_storage(ctx, rb, internalFormat, width, height); |
| |
| rb->Data = _mesa_malloc(height * xrb->pitch); |
| |
| return GL_TRUE; |
| } |
| |
| static struct swrast_renderbuffer * |
| swrast_new_renderbuffer(const GLvisual *visual, GLboolean front) |
| { |
| struct swrast_renderbuffer *xrb = _mesa_calloc(sizeof *xrb); |
| GLuint pixel_format; |
| |
| TRACE; |
| |
| if (!xrb) |
| return NULL; |
| |
| _mesa_init_renderbuffer(&xrb->Base, 0); |
| |
| pixel_format = choose_pixel_format(visual); |
| |
| xrb->Base.Delete = swrast_delete_renderbuffer; |
| if (front) { |
| xrb->Base.AllocStorage = swrast_alloc_front_storage; |
| swrast_set_span_funcs_front(xrb, pixel_format); |
| } |
| else { |
| xrb->Base.AllocStorage = swrast_alloc_back_storage; |
| swrast_set_span_funcs_back(xrb, pixel_format); |
| } |
| |
| switch (pixel_format) { |
| case PF_A8R8G8B8: |
| xrb->Base.InternalFormat = GL_RGBA; |
| xrb->Base._BaseFormat = GL_RGBA; |
| xrb->Base.DataType = GL_UNSIGNED_BYTE; |
| xrb->Base.RedBits = 8 * sizeof(GLubyte); |
| xrb->Base.GreenBits = 8 * sizeof(GLubyte); |
| xrb->Base.BlueBits = 8 * sizeof(GLubyte); |
| xrb->Base.AlphaBits = 8 * sizeof(GLubyte); |
| break; |
| case PF_R5G6B5: |
| xrb->Base.InternalFormat = GL_RGB; |
| xrb->Base._BaseFormat = GL_RGB; |
| xrb->Base.DataType = GL_UNSIGNED_BYTE; |
| xrb->Base.RedBits = 5 * sizeof(GLubyte); |
| xrb->Base.GreenBits = 6 * sizeof(GLubyte); |
| xrb->Base.BlueBits = 5 * sizeof(GLubyte); |
| xrb->Base.AlphaBits = 0; |
| break; |
| case PF_R3G3B2: |
| xrb->Base.InternalFormat = GL_RGB; |
| xrb->Base._BaseFormat = GL_RGB; |
| xrb->Base.DataType = GL_UNSIGNED_BYTE; |
| xrb->Base.RedBits = 3 * sizeof(GLubyte); |
| xrb->Base.GreenBits = 3 * sizeof(GLubyte); |
| xrb->Base.BlueBits = 2 * sizeof(GLubyte); |
| xrb->Base.AlphaBits = 0; |
| break; |
| case PF_CI8: |
| xrb->Base.InternalFormat = GL_COLOR_INDEX8_EXT; |
| xrb->Base._BaseFormat = GL_COLOR_INDEX; |
| xrb->Base.DataType = GL_UNSIGNED_BYTE; |
| xrb->Base.IndexBits = 8 * sizeof(GLubyte); |
| break; |
| default: |
| return NULL; |
| } |
| |
| return xrb; |
| } |
| |
| static __DRIdrawable * |
| driCreateNewDrawable(__DRIscreen *screen, |
| const __DRIconfig *config, void *data) |
| { |
| __DRIdrawable *buf; |
| struct swrast_renderbuffer *frontrb, *backrb; |
| |
| TRACE; |
| |
| buf = _mesa_calloc(sizeof *buf); |
| if (!buf) |
| return NULL; |
| |
| buf->loaderPrivate = data; |
| |
| buf->driScreenPriv = screen; |
| |
| buf->row = _mesa_malloc(MAX_WIDTH * 4); |
| |
| /* basic framebuffer setup */ |
| _mesa_initialize_framebuffer(&buf->Base, &config->modes); |
| |
| /* add front renderbuffer */ |
| frontrb = swrast_new_renderbuffer(&config->modes, GL_TRUE); |
| _mesa_add_renderbuffer(&buf->Base, BUFFER_FRONT_LEFT, &frontrb->Base); |
| |
| /* add back renderbuffer */ |
| if (config->modes.doubleBufferMode) { |
| backrb = swrast_new_renderbuffer(&config->modes, GL_FALSE); |
| _mesa_add_renderbuffer(&buf->Base, BUFFER_BACK_LEFT, &backrb->Base); |
| } |
| |
| /* add software renderbuffers */ |
| _mesa_add_soft_renderbuffers(&buf->Base, |
| GL_FALSE, /* color */ |
| config->modes.haveDepthBuffer, |
| config->modes.haveStencilBuffer, |
| config->modes.haveAccumBuffer, |
| GL_FALSE, /* alpha */ |
| GL_FALSE /* aux bufs */); |
| |
| return buf; |
| } |
| |
| static void |
| driDestroyDrawable(__DRIdrawable *buf) |
| { |
| TRACE; |
| |
| if (buf) { |
| struct gl_framebuffer *fb = &buf->Base; |
| |
| _mesa_free(buf->row); |
| |
| fb->DeletePending = GL_TRUE; |
| _mesa_unreference_framebuffer(&fb); |
| } |
| } |
| |
| static void driSwapBuffers(__DRIdrawable *buf) |
| { |
| GET_CURRENT_CONTEXT(ctx); |
| |
| struct swrast_renderbuffer *frontrb = |
| swrast_renderbuffer(buf->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer); |
| struct swrast_renderbuffer *backrb = |
| swrast_renderbuffer(buf->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer); |
| |
| __DRIscreen *screen = buf->driScreenPriv; |
| |
| TRACE; |
| |
| /* check for signle-buffered */ |
| if (backrb == NULL) |
| return; |
| |
| /* check if swapping currently bound buffer */ |
| if (ctx && ctx->DrawBuffer == &(buf->Base)) { |
| /* flush pending rendering */ |
| _mesa_notifySwapBuffers(ctx); |
| } |
| |
| screen->swrast_loader->putImage(buf, __DRI_SWRAST_IMAGE_OP_SWAP, |
| 0, 0, |
| frontrb->Base.Width, |
| frontrb->Base.Height, |
| backrb->Base.Data, |
| buf->loaderPrivate); |
| } |
| |
| |
| /** |
| * General device driver functions. |
| */ |
| |
| static void |
| get_window_size( GLframebuffer *fb, GLsizei *w, GLsizei *h ) |
| { |
| __DRIdrawable *buf = swrast_drawable(fb); |
| __DRIscreen *screen = buf->driScreenPriv; |
| int x, y; |
| |
| screen->swrast_loader->getDrawableInfo(buf, |
| &x, &y, w, h, |
| buf->loaderPrivate); |
| } |
| |
| static void |
| swrast_check_and_update_window_size( GLcontext *ctx, GLframebuffer *fb ) |
| { |
| GLsizei width, height; |
| |
| get_window_size(fb, &width, &height); |
| if (fb->Width != width || fb->Height != height) { |
| _mesa_resize_framebuffer(ctx, fb, width, height); |
| } |
| } |
| |
| static const GLubyte * |
| get_string(GLcontext *ctx, GLenum pname) |
| { |
| (void) ctx; |
| switch (pname) { |
| case GL_VENDOR: |
| return (const GLubyte *) "Mesa Project"; |
| case GL_RENDERER: |
| return (const GLubyte *) "Software Rasterizer"; |
| default: |
| return NULL; |
| } |
| } |
| |
| static void |
| update_state( GLcontext *ctx, GLuint new_state ) |
| { |
| /* not much to do here - pass it on */ |
| _swrast_InvalidateState( ctx, new_state ); |
| _swsetup_InvalidateState( ctx, new_state ); |
| _vbo_InvalidateState( ctx, new_state ); |
| _tnl_InvalidateState( ctx, new_state ); |
| } |
| |
| static void |
| viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h) |
| { |
| GLframebuffer *draw = ctx->WinSysDrawBuffer; |
| GLframebuffer *read = ctx->WinSysReadBuffer; |
| |
| swrast_check_and_update_window_size(ctx, draw); |
| swrast_check_and_update_window_size(ctx, read); |
| } |
| |
| static void |
| swrast_init_driver_functions(struct dd_function_table *driver) |
| { |
| driver->GetString = get_string; |
| driver->UpdateState = update_state; |
| driver->GetBufferSize = NULL; |
| driver->Viewport = viewport; |
| } |
| |
| |
| /** |
| * Context-related functions. |
| */ |
| |
| static __DRIcontext * |
| driCreateNewContext(__DRIscreen *screen, const __DRIconfig *config, |
| __DRIcontext *shared, void *data) |
| { |
| __DRIcontext *ctx; |
| GLcontext *mesaCtx; |
| struct dd_function_table functions; |
| |
| TRACE; |
| |
| ctx = _mesa_calloc(sizeof *ctx); |
| if (!ctx) |
| return NULL; |
| |
| ctx->loaderPrivate = data; |
| |
| ctx->driScreenPriv = screen; |
| |
| /* build table of device driver functions */ |
| _mesa_init_driver_functions(&functions); |
| swrast_init_driver_functions(&functions); |
| |
| if (!_mesa_initialize_context(&ctx->Base, &config->modes, |
| shared ? &shared->Base : NULL, |
| &functions, (void *) ctx)) { |
| _mesa_free(ctx); |
| return NULL; |
| } |
| |
| mesaCtx = &ctx->Base; |
| |
| /* do bounds checking to prevent segfaults and server crashes! */ |
| mesaCtx->Const.CheckArrayBounds = GL_TRUE; |
| |
| /* create module contexts */ |
| _swrast_CreateContext( mesaCtx ); |
| _vbo_CreateContext( mesaCtx ); |
| _tnl_CreateContext( mesaCtx ); |
| _swsetup_CreateContext( mesaCtx ); |
| _swsetup_Wakeup( mesaCtx ); |
| |
| /* use default TCL pipeline */ |
| { |
| TNLcontext *tnl = TNL_CONTEXT(mesaCtx); |
| tnl->Driver.RunPipeline = _tnl_run_pipeline; |
| } |
| |
| _mesa_enable_sw_extensions(mesaCtx); |
| _mesa_enable_1_3_extensions(mesaCtx); |
| _mesa_enable_1_4_extensions(mesaCtx); |
| _mesa_enable_1_5_extensions(mesaCtx); |
| _mesa_enable_2_0_extensions(mesaCtx); |
| _mesa_enable_2_1_extensions(mesaCtx); |
| |
| return ctx; |
| } |
| |
| static void |
| driDestroyContext(__DRIcontext *ctx) |
| { |
| GLcontext *mesaCtx; |
| TRACE; |
| |
| if (ctx) { |
| mesaCtx = &ctx->Base; |
| _swsetup_DestroyContext( mesaCtx ); |
| _swrast_DestroyContext( mesaCtx ); |
| _tnl_DestroyContext( mesaCtx ); |
| _vbo_DestroyContext( mesaCtx ); |
| _mesa_destroy_context( mesaCtx ); |
| } |
| } |
| |
| static int |
| driCopyContext(__DRIcontext *dst, __DRIcontext *src, unsigned long mask) |
| { |
| TRACE; |
| |
| _mesa_copy_context(&src->Base, &dst->Base, mask); |
| return GL_TRUE; |
| } |
| |
| static int driBindContext(__DRIcontext *ctx, |
| __DRIdrawable *draw, |
| __DRIdrawable *read) |
| { |
| GLcontext *mesaCtx; |
| GLframebuffer *mesaDraw; |
| GLframebuffer *mesaRead; |
| TRACE; |
| |
| if (ctx) { |
| if (!draw || !read) |
| return GL_FALSE; |
| |
| mesaCtx = &ctx->Base; |
| mesaDraw = &draw->Base; |
| mesaRead = &read->Base; |
| |
| /* check for same context and buffer */ |
| if (mesaCtx == _mesa_get_current_context() |
| && mesaCtx->DrawBuffer == mesaDraw |
| && mesaCtx->ReadBuffer == mesaRead) { |
| return GL_TRUE; |
| } |
| |
| _glapi_check_multithread(); |
| |
| swrast_check_and_update_window_size(mesaCtx, mesaDraw); |
| if (read != draw) |
| swrast_check_and_update_window_size(mesaCtx, mesaRead); |
| |
| _mesa_make_current( mesaCtx, |
| mesaDraw, |
| mesaRead ); |
| } |
| else { |
| /* unbind */ |
| _mesa_make_current( NULL, NULL, NULL ); |
| } |
| |
| return GL_TRUE; |
| } |
| |
| static int driUnbindContext(__DRIcontext *ctx) |
| { |
| TRACE; |
| (void) ctx; |
| return GL_TRUE; |
| } |
| |
| |
| static const __DRIcoreExtension driCoreExtension = { |
| { __DRI_CORE, __DRI_CORE_VERSION }, |
| NULL, /* driCreateNewScreen */ |
| driDestroyScreen, |
| driGetExtensions, |
| driGetConfigAttrib, |
| driIndexConfigAttrib, |
| NULL, /* driCreateNewDrawable */ |
| driDestroyDrawable, |
| driSwapBuffers, |
| driCreateNewContext, |
| driCopyContext, |
| driDestroyContext, |
| driBindContext, |
| driUnbindContext |
| }; |
| |
| static const __DRIswrastExtension driSWRastExtension = { |
| { __DRI_SWRAST, __DRI_SWRAST_VERSION }, |
| driCreateNewScreen, |
| driCreateNewDrawable |
| }; |
| |
| /* This is the table of extensions that the loader will dlsym() for. */ |
| PUBLIC const __DRIextension *__driDriverExtensions[] = { |
| &driCoreExtension.base, |
| &driSWRastExtension.base, |
| NULL |
| }; |