/* * Direct Rendering Support for SMedia Glamo 336x/337x * * (c) 2009 Thomas White * Roughly based on sis_context.c (c) 2003 Eric Anholt * and radeon_common_context.c * * 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 * THE AUTHORS 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. */ #include "dri_util.h" #include "drirenderbuffer.h" #include "utils.h" #include "swrast/swrast.h" #include "swrast_setup/swrast_setup.h" #include "drivers/common/driverfuncs.h" #include "vbo/vbo.h" #include "tnl/tnl.h" #include "tnl/t_pipeline.h" #include "main/state.h" #include "glamo_context.h" #include "glamo_screen.h" #include "glamo_state.h" #include "glamo_fbo.h" #include "glamo_tris.h" #include "glamo_render.h" #include "glamo_cmdq.h" #include #include #include #define DRIVER_DATE "20090913" static inline struct glamo_renderbuffer *glamo_get_renderbuffer( struct gl_framebuffer *fb, int att_index) { if ( att_index >= 0 ) { struct glamo_renderbuffer *gr; gr = glamo_renderbuffer(fb->Attachment[att_index].Renderbuffer); return gr; } else { return NULL; } } static const GLubyte *glamoGetString(GLcontext *ctx, GLenum name) { static char buffer[128]; switch (name) { case GL_VENDOR: return (GLubyte *)"Thomas White"; case GL_RENDERER: { driGetRendererString(buffer, "Glamo", DRIVER_DATE, 0); return (GLubyte *) buffer; } default: return 0; } } /* Called when Mesa needs to know the size of the framebuffer */ static void glamoBufferSize(GLframebuffer *buffer, GLuint *width, GLuint *height) { GET_CURRENT_CONTEXT(ctx); glamoContextPtr glamo = GLAMO_CONTEXT(ctx); *width = glamo->driDrawable->w; *height = glamo->driDrawable->h; } GLboolean glamoCreateContext(const __GLcontextModes *glVisual, __DRIcontext *driContextPriv, void *sharedContextPrivate) { GLcontext *ctx, *shareCtx; __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv; glamoContextPtr context; glamoScreenPtr glamoScreen; struct dd_function_table functions; context = (glamoContextPtr)CALLOC(sizeof(*context)); if ( context == NULL ) return GL_FALSE; _mesa_init_driver_functions(&functions); /* Allocate the Mesa context */ if ( sharedContextPrivate ) shareCtx = ((glamoContextPtr)sharedContextPrivate)->glCtx; else shareCtx = NULL; context->glCtx = _mesa_create_context(glVisual, shareCtx, &functions, (void *)context); if ( context->glCtx == NULL ) { FREE(context); return GL_FALSE; } driContextPriv->driverPrivate = context; ctx = context->glCtx; glamoScreen = context->glamoScreen = (glamoScreenPtr)sPriv->private; ctx->Driver.GetString = glamoGetString; ctx->Driver.GetBufferSize = glamoBufferSize; context->driContext = driContextPriv; context->driScreen = sPriv; context->driDrawable = NULL; context->drm_fd = sPriv->fd; /* Initialize the software rasterizer and helper modules. */ _swrast_CreateContext(ctx); _vbo_CreateContext(ctx); _tnl_CreateContext(ctx); _swsetup_CreateContext(ctx); /* Install our pipeline (see glamo_render.c) */ _tnl_install_pipeline(ctx, glamo_pipeline); _swrast_allow_pixel_fog(ctx, GL_TRUE); _swrast_allow_vertex_fog(ctx, GL_FALSE); _tnl_allow_pixel_fog(ctx, GL_TRUE); _tnl_allow_vertex_fog(ctx, GL_FALSE); glamoInitCmdqCache(context); glamoInitStateFuncs(ctx); glamoInitTriFuncs(ctx); return GL_TRUE; } void glamoDestroyContext(__DRIcontext *driContextPriv) { glamoContextPtr context; context = (glamoContextPtr)driContextPriv->driverPrivate; assert(context != NULL); if ( context != NULL ) { _swsetup_DestroyContext(context->glCtx); _tnl_DestroyContext(context->glCtx); _vbo_DestroyContext(context->glCtx); _swrast_DestroyContext(context->glCtx); _mesa_destroy_context(context->glCtx); } FREE(context); } void glamo_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable) { unsigned int attachments[10]; __DRIbuffer *buffers; __DRIscreen *screen; int i, count; struct glamo_framebuffer *draw; glamoContextPtr glamo; struct glamo_bo *bo; draw = drawable->driverPrivate; screen = context->driScreenPriv; glamo = (glamoContextPtr)context->driverPrivate; i = 0; if ( draw->color_rb[0] ) { attachments[i++] = __DRI_BUFFER_FRONT_LEFT; } if ( draw->color_rb[1] ) { attachments[i++] = __DRI_BUFFER_BACK_LEFT; } buffers = screen->dri2.loader->getBuffers(drawable, &drawable->w, &drawable->h, attachments, i, &count, drawable->loaderPrivate); if ( buffers == NULL ) return; /* Set one cliprect to cover the whole drawable */ drawable->x = 0; drawable->y = 0; drawable->backX = 0; drawable->backY = 0; drawable->numClipRects = 1; drawable->pClipRects[0].x1 = 0; drawable->pClipRects[0].y1 = 0; drawable->pClipRects[0].x2 = drawable->w; drawable->pClipRects[0].y2 = drawable->h; drawable->numBackClipRects = 1; drawable->pBackClipRects[0].x1 = 0; drawable->pBackClipRects[0].y1 = 0; drawable->pBackClipRects[0].x2 = drawable->w; drawable->pBackClipRects[0].y2 = drawable->h; /* For each attachment */ for ( i=0; icolor_rb[0]; break; case __DRI_BUFFER_BACK_LEFT: grb = draw->color_rb[1]; break; case __DRI_BUFFER_DEPTH: grb = glamo_get_renderbuffer(&draw->base, BUFFER_DEPTH); break; case __DRI_BUFFER_STENCIL: grb = glamo_get_renderbuffer(&draw->base, BUFFER_STENCIL); break; case __DRI_BUFFER_FAKE_FRONT_LEFT: grb = draw->color_rb[0]; break; case __DRI_BUFFER_ACCUM: default: fprintf(stderr, "Unhandled buffer attach event," " attachment type %d\n", buffers[i].attachment); return; } if ( grb == NULL ) { /* Don't know how to handle this type of buffer */ continue; } if ( grb->bo ) { uint32_t name = glamo_gem_get_name(grb->bo); if ( name == buffers[i].name ) { /* Buffer already attached. No action needed */ continue; } } grb->cpp = buffers[i].cpp; grb->pitch = buffers[i].pitch; grb->width = drawable->w; grb->height = drawable->h; bo = glamo_bo_open(glamo->glamoScreen->bom, buffers[i].name, 0, 0, GLAMO_GEM_DOMAIN_VRAM, buffers[i].flags); if ( bo == NULL ) { fprintf(stderr, "Failed to attach buffer %d\n", buffers[i].name); } glamo_renderbuffer_set_bo(grb, bo); glamo_bo_unref(bo); } driUpdateFramebufferSize(glamo->glCtx, drawable); } GLboolean glamoMakeCurrent(__DRIcontext *driContextPriv, __DRIdrawable *driDrawPriv, __DRIdrawable *driReadPriv) { struct glamo_framebuffer *draw_fb; struct gl_framebuffer *read_fb; glamoContextPtr glamo; if ( driContextPriv == NULL ) { _mesa_make_current(NULL, NULL, NULL); return GL_TRUE; } /* The Glamo context we're switching to */ glamo = (glamoContextPtr)driContextPriv->driverPrivate; glamo->driDrawable = driDrawPriv; /* These two will probably be the same */ draw_fb = (struct glamo_framebuffer *)driDrawPriv->driverPrivate; read_fb = (struct gl_framebuffer *)driReadPriv->driverPrivate; glamo_update_renderbuffers(driContextPriv, driDrawPriv); if (driDrawPriv != driReadPriv) glamo_update_renderbuffers(driContextPriv, driReadPriv); _mesa_make_current(glamo->glCtx, &draw_fb->base, read_fb); _mesa_update_state(glamo->glCtx); return GL_TRUE; } GLboolean glamoUnbindContext(__DRIcontext *driContextPriv) { return GL_TRUE; } /* Convert IEEE754 32-bit float to Glamo's signed 24-bit float */ uint32_t float7s16(GLfloat in) { uint32_t a, b; uint32_t sign, expo, mant; /* Sign, exponent, significand */ a = *(uint32_t *)∈ /* This is bad */ if ( a & 0x40000000 ) { printf(stderr, "Warning: Exponent won't fit into 7 bits\n"); } /* This hopefully isn't a big problem */ if ( a & 0x0000007f ) { printf(stderr, "Warning: Precision lost in FP conversion\n"); } /* Separate out the right bits */ mant = a & 0x007fff80; /* Bits 7-22 (bits 0-6 are lost) */ expo = a & 0x3f800000; /* Bits 23-29 (bit 30 is lost) */ sign = a & 0x80000000; /* Bit 31 */ /* Shift and recombine */ b = sign >> 8; /* Fills bit 23 */ b |= expo >> 7; /* Fills bits 16-22 */ b |= mant >> 7; /* Fills bits 0-15 */ return b; }