/* * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. * * 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, sub license, * 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 (including the * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS 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. */ /** * \file via_context.c * * \author John Sheng (presumably of either VIA Technologies or S3 Graphics) * \author Others at VIA Technologies? * \author Others at S3 Graphics? */ #include "main/glheader.h" #include "main/context.h" #include "main/formats.h" #include "main/simple_list.h" #include "main/framebuffer.h" #include "main/renderbuffer.h" #include "swrast/swrast.h" #include "swrast_setup/swrast_setup.h" #include "tnl/tnl.h" #include "vbo/vbo.h" #include "tnl/t_pipeline.h" #include "drivers/common/driverfuncs.h" #include "via_screen.h" #include "via_dri.h" #include "via_state.h" #include "via_tex.h" #include "via_span.h" #include "via_tris.h" #include "via_ioctl.h" #include "via_fb.h" #include #include "main/macros.h" #include "drirenderbuffer.h" #define need_GL_ARB_point_parameters #define need_GL_EXT_fog_coord #define need_GL_EXT_secondary_color #include "main/remap_helper.h" #define DRIVER_DATE "20060710" #include "vblank.h" #include "utils.h" GLuint VIA_DEBUG = 0; /** * Return various strings for \c glGetString. * * \sa glGetString */ static const GLubyte *viaGetString(GLcontext *ctx, GLenum name) { static char buffer[128]; unsigned offset; switch (name) { case GL_VENDOR: return (GLubyte *)"VIA Technology"; case GL_RENDERER: { static const char * const chipset_names[] = { "UniChrome", "CastleRock (CLE266)", "UniChrome (KM400)", "UniChrome (K8M800)", "UniChrome (PM8x0/CN400)", }; struct via_context *vmesa = VIA_CONTEXT(ctx); unsigned id = vmesa->viaScreen->deviceID; offset = driGetRendererString( buffer, chipset_names[(id > VIA_PM800) ? 0 : id], DRIVER_DATE, 0 ); return (GLubyte *)buffer; } default: return NULL; } } /** * Calculate a width that satisfies the hardware's alignment requirements. * On the Unichrome hardware, each scanline must be aligned to a multiple of * 16 pixels. * * \param width Minimum buffer width, in pixels. * * \returns A pixel width that meets the alignment requirements. */ static INLINE unsigned buffer_align( unsigned width ) { return (width + 0x0f) & ~0x0f; } static void viaDeleteRenderbuffer(struct gl_renderbuffer *rb) { /* Don't free() since we're contained in via_context struct. */ } static GLboolean viaRenderbufferStorage(GLcontext *ctx, struct gl_renderbuffer *rb, GLenum internalFormat, GLuint width, GLuint height) { rb->Width = width; rb->Height = height; rb->InternalFormat = internalFormat; return GL_TRUE; } static void viaInitRenderbuffer(struct via_renderbuffer *vrb, GLenum format, __DRIdrawable *dPriv) { const GLuint name = 0; struct gl_renderbuffer *rb = & vrb->Base; vrb->dPriv = dPriv; _mesa_init_renderbuffer(rb, name); /* Make sure we're using a null-valued GetPointer routine */ assert(rb->GetPointer(NULL, rb, 0, 0) == NULL); rb->InternalFormat = format; if (format == GL_RGBA) { /* Color */ rb->_BaseFormat = GL_RGBA; rb->Format = MESA_FORMAT_ARGB8888; rb->DataType = GL_UNSIGNED_BYTE; } else if (format == GL_DEPTH_COMPONENT16) { /* Depth */ rb->_BaseFormat = GL_DEPTH_COMPONENT; /* we always Get/Put 32-bit Z values */ rb->Format = MESA_FORMAT_Z16; rb->DataType = GL_UNSIGNED_INT; } else if (format == GL_DEPTH_COMPONENT24) { /* Depth */ rb->_BaseFormat = GL_DEPTH_COMPONENT; /* we always Get/Put 32-bit Z values */ rb->Format = MESA_FORMAT_Z32; rb->DataType = GL_UNSIGNED_INT; } else { /* Stencil */ ASSERT(format == GL_STENCIL_INDEX8_EXT); rb->_BaseFormat = GL_STENCIL_INDEX; rb->Format = MESA_FORMAT_S8; rb->DataType = GL_UNSIGNED_BYTE; } rb->Delete = viaDeleteRenderbuffer; rb->AllocStorage = viaRenderbufferStorage; } /** * Calculate the framebuffer parameters for all buffers (front, back, depth, * and stencil) associated with the specified context. * * \warning * This function also calls \c AllocateBuffer to actually allocate the * buffers. * * \sa AllocateBuffer */ static GLboolean calculate_buffer_parameters(struct via_context *vmesa, struct gl_framebuffer *fb, __DRIdrawable *dPriv) { const unsigned shift = vmesa->viaScreen->bitsPerPixel / 16; const unsigned extra = 32; unsigned w; unsigned h; /* Normally, the renderbuffer would be added to the framebuffer just once * when the framebuffer was created. The VIA driver is a bit funny * though in that the front/back/depth renderbuffers are in the per-context * state! * That should be fixed someday. */ if (!vmesa->front.Base.InternalFormat) { /* do one-time init for the renderbuffers */ viaInitRenderbuffer(&vmesa->front, GL_RGBA, dPriv); viaSetSpanFunctions(&vmesa->front, &fb->Visual); _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &vmesa->front.Base); if (fb->Visual.doubleBufferMode) { viaInitRenderbuffer(&vmesa->back, GL_RGBA, dPriv); viaSetSpanFunctions(&vmesa->back, &fb->Visual); _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &vmesa->back.Base); } if (vmesa->glCtx->Visual.depthBits > 0) { viaInitRenderbuffer(&vmesa->depth, (vmesa->glCtx->Visual.depthBits == 16 ? GL_DEPTH_COMPONENT16 : GL_DEPTH_COMPONENT24), dPriv); viaSetSpanFunctions(&vmesa->depth, &fb->Visual); _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &vmesa->depth.Base); } if (vmesa->glCtx->Visual.stencilBits > 0) { viaInitRenderbuffer(&vmesa->stencil, GL_STENCIL_INDEX8_EXT, dPriv); viaSetSpanFunctions(&vmesa->stencil, &fb->Visual); _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &vmesa->stencil.Base); } } assert(vmesa->front.Base.InternalFormat); assert(vmesa->front.Base.AllocStorage); if (fb->Visual.doubleBufferMode) { assert(vmesa->back.Base.AllocStorage); } if (fb->Visual.depthBits) { assert(vmesa->depth.Base.AllocStorage); } /* Allocate front-buffer */ if (vmesa->drawType == GLX_PBUFFER_BIT) { w = vmesa->driDrawable->w; h = vmesa->driDrawable->h; vmesa->front.bpp = vmesa->viaScreen->bitsPerPixel; vmesa->front.pitch = buffer_align( w ) << shift; /* bytes, not pixels */ vmesa->front.size = vmesa->front.pitch * h; if (vmesa->front.map) via_free_draw_buffer(vmesa, &vmesa->front); if (!via_alloc_draw_buffer(vmesa, &vmesa->front)) return GL_FALSE; } else { w = vmesa->viaScreen->width; h = vmesa->viaScreen->height; vmesa->front.bpp = vmesa->viaScreen->bitsPerPixel; vmesa->front.pitch = buffer_align( w ) << shift; /* bytes, not pixels */ vmesa->front.size = vmesa->front.pitch * h; if (getenv("ALTERNATE_SCREEN")) vmesa->front.offset = vmesa->front.size; else vmesa->front.offset = 0; vmesa->front.map = (char *) vmesa->driScreen->pFB; } /* Allocate back-buffer */ if (vmesa->hasBack) { vmesa->back.bpp = vmesa->viaScreen->bitsPerPixel; vmesa->back.pitch = (buffer_align( vmesa->driDrawable->w ) << shift); vmesa->back.pitch += extra; vmesa->back.pitch = MIN2(vmesa->back.pitch, vmesa->front.pitch); vmesa->back.size = vmesa->back.pitch * vmesa->driDrawable->h; if (vmesa->back.map) via_free_draw_buffer(vmesa, &vmesa->back); if (!via_alloc_draw_buffer(vmesa, &vmesa->back)) return GL_FALSE; } else { if (vmesa->back.map) via_free_draw_buffer(vmesa, &vmesa->back); (void) memset( &vmesa->back, 0, sizeof( vmesa->back ) ); } /* Allocate depth-buffer */ if ( vmesa->hasStencil || vmesa->hasDepth ) { vmesa->depth.bpp = vmesa->depthBits; if (vmesa->depth.bpp == 24) vmesa->depth.bpp = 32; vmesa->depth.pitch = (buffer_align( vmesa->driDrawable->w ) * (vmesa->depth.bpp/8)) + extra; vmesa->depth.size = vmesa->depth.pitch * vmesa->driDrawable->h; if (vmesa->depth.map) via_free_draw_buffer(vmesa, &vmesa->depth); if (!via_alloc_draw_buffer(vmesa, &vmesa->depth)) { return GL_FALSE; } } else { if (vmesa->depth.map) via_free_draw_buffer(vmesa, &vmesa->depth); (void) memset( & vmesa->depth, 0, sizeof( vmesa->depth ) ); } /* stencil buffer is same as depth buffer */ vmesa->stencil.handle = vmesa->depth.handle; vmesa->stencil.size = vmesa->depth.size; vmesa->stencil.offset = vmesa->depth.offset; vmesa->stencil.index = vmesa->depth.index; vmesa->stencil.pitch = vmesa->depth.pitch; vmesa->stencil.bpp = vmesa->depth.bpp; vmesa->stencil.map = vmesa->depth.map; vmesa->stencil.orig = vmesa->depth.orig; vmesa->stencil.origMap = vmesa->depth.origMap; if( vmesa->viaScreen->width == vmesa->driDrawable->w && vmesa->viaScreen->height == vmesa->driDrawable->h ) { vmesa->doPageFlip = vmesa->allowPageFlip; if (vmesa->hasBack) { assert(vmesa->back.pitch == vmesa->front.pitch); } } else vmesa->doPageFlip = GL_FALSE; return GL_TRUE; } void viaReAllocateBuffers(GLcontext *ctx, struct gl_framebuffer *drawbuffer, GLuint width, GLuint height) { struct via_context *vmesa = VIA_CONTEXT(ctx); calculate_buffer_parameters(vmesa, drawbuffer, vmesa->driDrawable); _mesa_resize_framebuffer(ctx, drawbuffer, width, height); } /* Extension strings exported by the Unichrome driver. */ static const struct dri_extension card_extensions[] = { { "GL_ARB_multitexture", NULL }, { "GL_ARB_point_parameters", GL_ARB_point_parameters_functions }, { "GL_ARB_texture_env_add", NULL }, { "GL_ARB_texture_env_combine", NULL }, /* { "GL_ARB_texture_env_dot3", NULL }, */ { "GL_ARB_texture_mirrored_repeat", NULL }, { "GL_EXT_fog_coord", GL_EXT_fog_coord_functions }, { "GL_EXT_secondary_color", GL_EXT_secondary_color_functions }, { "GL_EXT_stencil_wrap", NULL }, { "GL_EXT_texture_env_combine", NULL }, /* { "GL_EXT_texture_env_dot3", NULL }, */ { "GL_EXT_texture_lod_bias", NULL }, { "GL_NV_blend_square", NULL }, { NULL, NULL } }; extern const struct tnl_pipeline_stage _via_fastrender_stage; extern const struct tnl_pipeline_stage _via_render_stage; static const struct tnl_pipeline_stage *via_pipeline[] = { &_tnl_vertex_transform_stage, &_tnl_normal_transform_stage, &_tnl_lighting_stage, &_tnl_fog_coordinate_stage, &_tnl_texgen_stage, &_tnl_texture_transform_stage, /* REMOVE: point attenuation stage */ #if 1 &_via_fastrender_stage, /* ADD: unclipped rastersetup-to-dma */ #endif &_tnl_render_stage, 0, }; static const struct dri_debug_control debug_control[] = { { "fall", DEBUG_FALLBACKS }, { "tex", DEBUG_TEXTURE }, { "ioctl", DEBUG_IOCTL }, { "prim", DEBUG_PRIMS }, { "vert", DEBUG_VERTS }, { "state", DEBUG_STATE }, { "verb", DEBUG_VERBOSE }, { "dri", DEBUG_DRI }, { "dma", DEBUG_DMA }, { "san", DEBUG_SANITY }, { "sync", DEBUG_SYNC }, { "sleep", DEBUG_SLEEP }, { "pix", DEBUG_PIXEL }, { "2d", DEBUG_2D }, { NULL, 0 } }; static GLboolean AllocateDmaBuffer(struct via_context *vmesa) { if (vmesa->dma) via_free_dma_buffer(vmesa); if (!via_alloc_dma_buffer(vmesa)) return GL_FALSE; vmesa->dmaLow = 0; vmesa->dmaCliprectAddr = ~0; return GL_TRUE; } static void FreeBuffer(struct via_context *vmesa) { if (vmesa->front.map && vmesa->drawType == GLX_PBUFFER_BIT) via_free_draw_buffer(vmesa, &vmesa->front); if (vmesa->back.map) via_free_draw_buffer(vmesa, &vmesa->back); if (vmesa->depth.map) via_free_draw_buffer(vmesa, &vmesa->depth); if (vmesa->breadcrumb.map) via_free_draw_buffer(vmesa, &vmesa->breadcrumb); if (vmesa->dma) via_free_dma_buffer(vmesa); } GLboolean viaCreateContext(gl_api api, const struct gl_config *visual, __DRIcontext *driContextPriv, void *sharedContextPrivate) { GLcontext *ctx, *shareCtx; struct via_context *vmesa; __DRIscreen *sPriv = driContextPriv->driScreenPriv; viaScreenPrivate *viaScreen = (viaScreenPrivate *)sPriv->private; drm_via_sarea_t *saPriv = (drm_via_sarea_t *) (((GLubyte *)sPriv->pSAREA) + viaScreen->sareaPrivOffset); struct dd_function_table functions; /* Allocate via context */ vmesa = (struct via_context *) CALLOC_STRUCT(via_context); if (!vmesa) { return GL_FALSE; } /* Parse configuration files. */ driParseConfigFiles (&vmesa->optionCache, &viaScreen->optionCache, sPriv->myNum, "unichrome"); /* pick back buffer */ vmesa->hasBack = visual->doubleBufferMode; switch(visual->depthBits) { case 0: vmesa->hasDepth = GL_FALSE; vmesa->depthBits = 0; vmesa->depth_max = 1.0; break; case 16: vmesa->hasDepth = GL_TRUE; vmesa->depthBits = visual->depthBits; vmesa->have_hw_stencil = GL_FALSE; vmesa->depth_max = (GLfloat)0xffff; vmesa->depth_clear_mask = 0xf << 28; vmesa->ClearDepth = 0xffff; vmesa->polygon_offset_scale = 1.0 / vmesa->depth_max; break; case 24: vmesa->hasDepth = GL_TRUE; vmesa->depthBits = visual->depthBits; vmesa->depth_max = (GLfloat) 0xffffff; vmesa->depth_clear_mask = 0xe << 28; vmesa->ClearDepth = 0xffffff00; assert(visual->haveStencilBuffer); assert(visual->stencilBits == 8); vmesa->have_hw_stencil = GL_TRUE; vmesa->stencilBits = visual->stencilBits; vmesa->stencil_clear_mask = 0x1 << 28; vmesa->polygon_offset_scale = 2.0 / vmesa->depth_max; break; case 32: vmesa->hasDepth = GL_TRUE; vmesa->depthBits = visual->depthBits; assert(!visual->haveStencilBuffer); vmesa->have_hw_stencil = GL_FALSE; vmesa->depth_max = (GLfloat)0xffffffff; vmesa->depth_clear_mask = 0xf << 28; vmesa->ClearDepth = 0xffffffff; vmesa->polygon_offset_scale = 2.0 / vmesa->depth_max; break; default: assert(0); break; } make_empty_list(&vmesa->freed_tex_buffers); make_empty_list(&vmesa->tex_image_list[VIA_MEM_VIDEO]); make_empty_list(&vmesa->tex_image_list[VIA_MEM_AGP]); make_empty_list(&vmesa->tex_image_list[VIA_MEM_SYSTEM]); _mesa_init_driver_functions(&functions); viaInitTextureFuncs(&functions); /* Allocate the Mesa context */ if (sharedContextPrivate) shareCtx = ((struct via_context *) sharedContextPrivate)->glCtx; else shareCtx = NULL; vmesa->glCtx = _mesa_create_context(visual, shareCtx, &functions, (void*) vmesa); vmesa->shareCtx = shareCtx; if (!vmesa->glCtx) { FREE(vmesa); return GL_FALSE; } driContextPriv->driverPrivate = vmesa; ctx = vmesa->glCtx; if (driQueryOptionb(&vmesa->optionCache, "excess_mipmap")) ctx->Const.MaxTextureLevels = 11; else ctx->Const.MaxTextureLevels = 10; ctx->Const.MaxTextureUnits = 2; ctx->Const.MaxTextureImageUnits = ctx->Const.MaxTextureUnits; ctx->Const.MaxTextureCoordUnits = ctx->Const.MaxTextureUnits; ctx->Const.MinLineWidth = 1.0; ctx->Const.MinLineWidthAA = 1.0; ctx->Const.MaxLineWidth = 1.0; ctx->Const.MaxLineWidthAA = 1.0; ctx->Const.LineWidthGranularity = 1.0; ctx->Const.MinPointSize = 1.0; ctx->Const.MinPointSizeAA = 1.0; ctx->Const.MaxPointSize = 1.0; ctx->Const.MaxPointSizeAA = 1.0; ctx->Const.PointSizeGranularity = 1.0; ctx->Const.MaxDrawBuffers = 1; ctx->Driver.GetString = viaGetString; ctx->DriverCtx = (void *)vmesa; vmesa->glCtx = ctx; /* Initialize the software rasterizer and helper modules. */ _swrast_CreateContext(ctx); _vbo_CreateContext(ctx); _tnl_CreateContext(ctx); _swsetup_CreateContext(ctx); /* Install the customized pipeline: */ _tnl_destroy_pipeline(ctx); _tnl_install_pipeline(ctx, via_pipeline); /* Configure swrast and T&L to match hardware characteristics: */ _swrast_allow_pixel_fog(ctx, GL_FALSE); _swrast_allow_vertex_fog(ctx, GL_TRUE); _tnl_allow_pixel_fog(ctx, GL_FALSE); _tnl_allow_vertex_fog(ctx, GL_TRUE); vmesa->hHWContext = driContextPriv->hHWContext; vmesa->driFd = sPriv->fd; vmesa->driHwLock = &sPriv->pSAREA->lock; vmesa->viaScreen = viaScreen; vmesa->driScreen = sPriv; vmesa->sarea = saPriv; vmesa->renderIndex = ~0; vmesa->setupIndex = ~0; vmesa->hwPrimitive = GL_POLYGON+1; /* KW: Hardwire this. Was previously set bogusly in * viaCreateBuffer. Needs work before PBUFFER can be used: */ vmesa->drawType = GLX_WINDOW_BIT; _math_matrix_ctr(&vmesa->ViewportMatrix); /* Do this early, before VIA_FLUSH_DMA can be called: */ if (!AllocateDmaBuffer(vmesa)) { fprintf(stderr ,"AllocateDmaBuffer fail\n"); FreeBuffer(vmesa); FREE(vmesa); return GL_FALSE; } /* Allocate a small piece of fb memory for synchronization: */ vmesa->breadcrumb.bpp = 32; vmesa->breadcrumb.pitch = buffer_align( 64 ) << 2; vmesa->breadcrumb.size = vmesa->breadcrumb.pitch; if (!via_alloc_draw_buffer(vmesa, &vmesa->breadcrumb)) { fprintf(stderr ,"AllocateDmaBuffer fail\n"); FreeBuffer(vmesa); FREE(vmesa); return GL_FALSE; } driInitExtensions( ctx, card_extensions, GL_TRUE ); viaInitStateFuncs(ctx); viaInitTriFuncs(ctx); viaInitSpanFuncs(ctx); viaInitIoctlFuncs(ctx); viaInitState(ctx); if (getenv("VIA_DEBUG")) VIA_DEBUG = driParseDebugString( getenv( "VIA_DEBUG" ), debug_control ); if (getenv("VIA_NO_RAST") || driQueryOptionb(&vmesa->optionCache, "no_rast")) FALLBACK(vmesa, VIA_FALLBACK_USER_DISABLE, 1); if (getenv("VIA_PAGEFLIP")) vmesa->allowPageFlip = 1; (*sPriv->systemTime->getUST)( &vmesa->swap_ust ); vmesa->regMMIOBase = (GLuint *)((unsigned long)viaScreen->reg); vmesa->pnGEMode = (GLuint *)((unsigned long)viaScreen->reg + 0x4); vmesa->regEngineStatus = (GLuint *)((unsigned long)viaScreen->reg + 0x400); vmesa->regTranSet = (GLuint *)((unsigned long)viaScreen->reg + 0x43C); vmesa->regTranSpace = (GLuint *)((unsigned long)viaScreen->reg + 0x440); vmesa->agpBase = viaScreen->agpBase; return GL_TRUE; } void viaDestroyContext(__DRIcontext *driContextPriv) { GET_CURRENT_CONTEXT(ctx); struct via_context *vmesa = (struct via_context *)driContextPriv->driverPrivate; struct via_context *current = ctx ? VIA_CONTEXT(ctx) : NULL; assert(vmesa); /* should never be null */ if (vmesa->driDrawable) { viaWaitIdle(vmesa, GL_FALSE); if (vmesa->doPageFlip) { LOCK_HARDWARE(vmesa); if (vmesa->pfCurrentOffset != 0) { fprintf(stderr, "%s - reset pf\n", __FUNCTION__); viaResetPageFlippingLocked(vmesa); } UNLOCK_HARDWARE(vmesa); } } /* check if we're deleting the currently bound context */ if (vmesa == current) { VIA_FLUSH_DMA(vmesa); _mesa_make_current(NULL, NULL, NULL); } _swsetup_DestroyContext(vmesa->glCtx); _tnl_DestroyContext(vmesa->glCtx); _vbo_DestroyContext(vmesa->glCtx); _swrast_DestroyContext(vmesa->glCtx); /* free the Mesa context */ _mesa_destroy_context(vmesa->glCtx); /* release our data */ FreeBuffer(vmesa); assert (is_empty_list(&vmesa->tex_image_list[VIA_MEM_AGP])); assert (is_empty_list(&vmesa->tex_image_list[VIA_MEM_VIDEO])); assert (is_empty_list(&vmesa->tex_image_list[VIA_MEM_SYSTEM])); assert (is_empty_list(&vmesa->freed_tex_buffers)); driDestroyOptionCache(&vmesa->optionCache); FREE(vmesa); } void viaXMesaWindowMoved(struct via_context *vmesa) { __DRIdrawable *const drawable = vmesa->driDrawable; __DRIdrawable *const readable = vmesa->driReadable; struct via_renderbuffer * draw_buffer; struct via_renderbuffer * read_buffer; GLuint bytePerPixel = vmesa->viaScreen->bitsPerPixel >> 3; if (!drawable) return; draw_buffer = (struct via_renderbuffer *) drawable->driverPrivate; read_buffer = (struct via_renderbuffer *) readable->driverPrivate; switch (vmesa->glCtx->DrawBuffer->_ColorDrawBufferIndexes[0]) { case BUFFER_BACK_LEFT: if (drawable->numBackClipRects == 0) { vmesa->numClipRects = drawable->numClipRects; vmesa->pClipRects = drawable->pClipRects; } else { vmesa->numClipRects = drawable->numBackClipRects; vmesa->pClipRects = drawable->pBackClipRects; } break; case BUFFER_FRONT_LEFT: vmesa->numClipRects = drawable->numClipRects; vmesa->pClipRects = drawable->pClipRects; break; default: vmesa->numClipRects = 0; break; } if ((draw_buffer->drawW != drawable->w) || (draw_buffer->drawH != drawable->h)) { calculate_buffer_parameters(vmesa, vmesa->glCtx->DrawBuffer, drawable); } draw_buffer->drawX = drawable->x; draw_buffer->drawY = drawable->y; draw_buffer->drawW = drawable->w; draw_buffer->drawH = drawable->h; if (drawable != readable) { if ((read_buffer->drawW != readable->w) || (read_buffer->drawH != readable->h)) { calculate_buffer_parameters(vmesa, vmesa->glCtx->ReadBuffer, readable); } read_buffer->drawX = readable->x; read_buffer->drawY = readable->y; read_buffer->drawW = readable->w; read_buffer->drawH = readable->h; } vmesa->front.orig = (vmesa->front.offset + draw_buffer->drawY * vmesa->front.pitch + draw_buffer->drawX * bytePerPixel); vmesa->front.origMap = (vmesa->front.map + draw_buffer->drawY * vmesa->front.pitch + draw_buffer->drawX * bytePerPixel); vmesa->back.orig = (vmesa->back.offset + draw_buffer->drawY * vmesa->back.pitch + draw_buffer->drawX * bytePerPixel); vmesa->back.origMap = (vmesa->back.map + draw_buffer->drawY * vmesa->back.pitch + draw_buffer->drawX * bytePerPixel); vmesa->depth.orig = (vmesa->depth.offset + draw_buffer->drawY * vmesa->depth.pitch + draw_buffer->drawX * bytePerPixel); vmesa->depth.origMap = (vmesa->depth.map + draw_buffer->drawY * vmesa->depth.pitch + draw_buffer->drawX * bytePerPixel); viaCalcViewport(vmesa->glCtx); } GLboolean viaUnbindContext(__DRIcontext *driContextPriv) { return GL_TRUE; } GLboolean viaMakeCurrent(__DRIcontext *driContextPriv, __DRIdrawable *driDrawPriv, __DRIdrawable *driReadPriv) { if (VIA_DEBUG & DEBUG_DRI) { fprintf(stderr, "driContextPriv = %016lx\n", (unsigned long)driContextPriv); fprintf(stderr, "driDrawPriv = %016lx\n", (unsigned long)driDrawPriv); fprintf(stderr, "driReadPriv = %016lx\n", (unsigned long)driReadPriv); } if (driContextPriv) { struct via_context *vmesa = (struct via_context *)driContextPriv->driverPrivate; GLcontext *ctx = vmesa->glCtx; struct gl_framebuffer *drawBuffer, *readBuffer; drawBuffer = (struct gl_framebuffer *)driDrawPriv->driverPrivate; readBuffer = (struct gl_framebuffer *)driReadPriv->driverPrivate; if ((vmesa->driDrawable != driDrawPriv) || (vmesa->driReadable != driReadPriv)) { if (driDrawPriv->swap_interval == (unsigned)-1) { driDrawPriv->vblFlags = vmesa->viaScreen->irqEnabled ? driGetDefaultVBlankFlags(&vmesa->optionCache) : VBLANK_FLAG_NO_IRQ; driDrawableInitVBlank(driDrawPriv); } vmesa->driDrawable = driDrawPriv; vmesa->driReadable = driReadPriv; if ((drawBuffer->Width != driDrawPriv->w) || (drawBuffer->Height != driDrawPriv->h)) { _mesa_resize_framebuffer(ctx, drawBuffer, driDrawPriv->w, driDrawPriv->h); drawBuffer->Initialized = GL_TRUE; } if (!calculate_buffer_parameters(vmesa, drawBuffer, driDrawPriv)) { return GL_FALSE; } if (driDrawPriv != driReadPriv) { if ((readBuffer->Width != driReadPriv->w) || (readBuffer->Height != driReadPriv->h)) { _mesa_resize_framebuffer(ctx, readBuffer, driReadPriv->w, driReadPriv->h); readBuffer->Initialized = GL_TRUE; } if (!calculate_buffer_parameters(vmesa, readBuffer, driReadPriv)) { return GL_FALSE; } } } _mesa_make_current(vmesa->glCtx, drawBuffer, readBuffer); ctx->Driver.DrawBuffer( ctx, ctx->Color.DrawBuffer[0] ); viaXMesaWindowMoved(vmesa); ctx->Driver.Scissor(vmesa->glCtx, vmesa->glCtx->Scissor.X, vmesa->glCtx->Scissor.Y, vmesa->glCtx->Scissor.Width, vmesa->glCtx->Scissor.Height); } else { _mesa_make_current(NULL, NULL, NULL); } return GL_TRUE; } void viaGetLock(struct via_context *vmesa, GLuint flags) { __DRIdrawable *dPriv = vmesa->driDrawable; __DRIscreen *sPriv = vmesa->driScreen; drmGetLock(vmesa->driFd, vmesa->hHWContext, flags); DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv); if (dPriv != vmesa->driReadable) { DRI_VALIDATE_DRAWABLE_INFO(sPriv, vmesa->driReadable); } if (vmesa->sarea->ctxOwner != vmesa->hHWContext) { vmesa->sarea->ctxOwner = vmesa->hHWContext; vmesa->newEmitState = ~0; } if (vmesa->lastStamp != dPriv->lastStamp) { viaXMesaWindowMoved(vmesa); driUpdateFramebufferSize(vmesa->glCtx, dPriv); vmesa->newEmitState = ~0; vmesa->lastStamp = dPriv->lastStamp; } if (vmesa->doPageFlip && vmesa->pfCurrentOffset != vmesa->sarea->pfCurrentOffset) { fprintf(stderr, "%s - reset pf\n", __FUNCTION__); viaResetPageFlippingLocked(vmesa); } } void viaSwapBuffers(__DRIdrawable *drawablePrivate) { __DRIdrawable *dPriv = (__DRIdrawable *)drawablePrivate; if (dPriv && dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) { struct via_context *vmesa = (struct via_context *)dPriv->driContextPriv->driverPrivate; GLcontext *ctx = vmesa->glCtx; _mesa_notifySwapBuffers(ctx); if (ctx->Visual.doubleBufferMode) { if (vmesa->doPageFlip) { viaPageFlip(dPriv); } else { viaCopyBuffer(dPriv); } } else VIA_FLUSH_DMA(vmesa); } else { _mesa_problem(NULL, "viaSwapBuffers: drawable has no context!\n"); } }