📄 fb_dri.c
字号:
_mesa_make_current(NULL, NULL, NULL); } /* Free fb context resources */ if ( fbmesa ) { _swsetup_DestroyContext( fbmesa->glCtx ); _tnl_DestroyContext( fbmesa->glCtx ); _vbo_DestroyContext( fbmesa->glCtx ); _swrast_DestroyContext( fbmesa->glCtx ); /* free the Mesa context */ fbmesa->glCtx->DriverCtx = NULL; _mesa_destroy_context( fbmesa->glCtx ); _mesa_free( fbmesa ); }}/* Create and initialize the Mesa and driver specific pixmap buffer * data. */static GLbooleanfbCreateBuffer( __DRIscreenPrivate *driScrnPriv, __DRIdrawablePrivate *driDrawPriv, const __GLcontextModes *mesaVis, GLboolean isPixmap ){ struct gl_framebuffer *mesa_framebuffer; if (isPixmap) { return GL_FALSE; /* not implemented */ } else { const GLboolean swDepth = mesaVis->depthBits > 0; const GLboolean swAlpha = mesaVis->alphaBits > 0; const GLboolean swAccum = mesaVis->accumRedBits > 0; const GLboolean swStencil = mesaVis->stencilBits > 0; mesa_framebuffer = _mesa_create_framebuffer(mesaVis); if (!mesa_framebuffer) return 0; /* XXX double-check these parameters (bpp vs cpp, etc) */ { driRenderbuffer *drb = driNewRenderbuffer(GL_RGBA, driScrnPriv->pFB, driScrnPriv->fbBPP / 8, driScrnPriv->fbOrigin, driScrnPriv->fbStride, driDrawPriv); fbSetSpanFunctions(drb, mesaVis); _mesa_add_renderbuffer(mesa_framebuffer, BUFFER_FRONT_LEFT, &drb->Base); } if (mesaVis->doubleBufferMode) { /* XXX what are the correct origin/stride values? */ GLvoid *backBuf = _mesa_malloc(driScrnPriv->fbStride * driScrnPriv->fbHeight); driRenderbuffer *drb = driNewRenderbuffer(GL_RGBA, backBuf, driScrnPriv->fbBPP /8, driScrnPriv->fbOrigin, driScrnPriv->fbStride, driDrawPriv); fbSetSpanFunctions(drb, mesaVis); _mesa_add_renderbuffer(mesa_framebuffer, BUFFER_BACK_LEFT, &drb->Base); } _mesa_add_soft_renderbuffers(mesa_framebuffer, GL_FALSE, /* color */ swDepth, swStencil, swAccum, swAlpha, /* or always zero? */ GL_FALSE /* aux */); driDrawPriv->driverPrivate = mesa_framebuffer; return 1; }}static voidfbDestroyBuffer(__DRIdrawablePrivate *driDrawPriv){ _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));}/* If the backbuffer is on a videocard, this is extraordinarily slow! */static voidfbSwapBuffers( __DRIdrawablePrivate *dPriv ){ struct gl_framebuffer *mesa_framebuffer = (struct gl_framebuffer *)dPriv->driverPrivate; struct gl_renderbuffer * front_renderbuffer = mesa_framebuffer->Attachment[BUFFER_FRONT_LEFT].Renderbuffer; void *frontBuffer = front_renderbuffer->Data; int currentPitch = ((driRenderbuffer *)front_renderbuffer)->pitch; void *backBuffer = mesa_framebuffer->Attachment[BUFFER_BACK_LEFT].Renderbuffer->Data; if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) { fbContextPtr fbmesa = (fbContextPtr) dPriv->driContextPriv->driverPrivate; GLcontext *ctx = fbmesa->glCtx; if (ctx->Visual.doubleBufferMode) { int i; int offset = 0; char *tmp = _mesa_malloc(currentPitch); _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */ ASSERT(frontBuffer); ASSERT(backBuffer); for (i = 0; i < dPriv->h; i++) { _mesa_memcpy(tmp, (char *) backBuffer + offset, currentPitch); _mesa_memcpy((char *) frontBuffer + offset, tmp, currentPitch); offset += currentPitch; } _mesa_free(tmp); } } else { /* XXX this shouldn't be an error but we can't handle it for now */ _mesa_problem(NULL, "fbSwapBuffers: drawable has no context!\n"); }}/* Force the context `c' to be the current context and associate with it * buffer `b'. */static GLbooleanfbMakeCurrent( __DRIcontextPrivate *driContextPriv, __DRIdrawablePrivate *driDrawPriv, __DRIdrawablePrivate *driReadPriv ){ if ( driContextPriv ) { fbContextPtr newFbCtx = (fbContextPtr) driContextPriv->driverPrivate; newFbCtx->dri.drawable = driDrawPriv; _mesa_make_current( newFbCtx->glCtx, driDrawPriv->driverPrivate, driReadPriv->driverPrivate); } else { _mesa_make_current( NULL, NULL, NULL ); } return GL_TRUE;}/* Force the context `c' to be unbound from its buffer. */static GLbooleanfbUnbindContext( __DRIcontextPrivate *driContextPriv ){ return GL_TRUE;}static struct __DriverAPIRec fbAPI = { .InitDriver = fbInitDriver, .DestroyScreen = fbDestroyScreen, .CreateContext = fbCreateContext, .DestroyContext = fbDestroyContext, .CreateBuffer = fbCreateBuffer, .DestroyBuffer = fbDestroyBuffer, .SwapBuffers = fbSwapBuffers, .MakeCurrent = fbMakeCurrent, .UnbindContext = fbUnbindContext,};static int__driValidateMode(const DRIDriverContext *ctx ){ return 1;}static int__driInitFBDev( struct DRIDriverContextRec *ctx ){ /* Note that drmOpen will try to load the kernel module, if needed. */ /* we need a fbdev drm driver - it will only track maps */ ctx->drmFD = drmOpen("radeon", NULL ); if (ctx->drmFD < 0) { fprintf(stderr, "[drm] drmOpen failed\n"); return 0; } ctx->shared.SAREASize = SAREA_MAX; if (drmAddMap( ctx->drmFD, 0, ctx->shared.SAREASize, DRM_SHM, DRM_CONTAINS_LOCK, &ctx->shared.hSAREA) < 0) { fprintf(stderr, "[drm] drmAddMap failed\n"); return 0; } fprintf(stderr, "[drm] added %d byte SAREA at 0x%08lx\n", ctx->shared.SAREASize, (unsigned long) ctx->shared.hSAREA); if (drmMap( ctx->drmFD, ctx->shared.hSAREA, ctx->shared.SAREASize, (drmAddressPtr)(&ctx->pSAREA)) < 0) { fprintf(stderr, "[drm] drmMap failed\n"); return 0; } memset(ctx->pSAREA, 0, ctx->shared.SAREASize); fprintf(stderr, "[drm] mapped SAREA 0x%08lx to %p, size %d\n", (unsigned long) ctx->shared.hSAREA, ctx->pSAREA, ctx->shared.SAREASize); /* Need to AddMap the framebuffer and mmio regions here: */ if (drmAddMap( ctx->drmFD, (drm_handle_t)ctx->FBStart, ctx->FBSize, DRM_FRAME_BUFFER,#ifndef _EMBEDDED 0,#else DRM_READ_ONLY,#endif &ctx->shared.hFrameBuffer) < 0) { fprintf(stderr, "[drm] drmAddMap framebuffer failed\n"); return 0; } fprintf(stderr, "[drm] framebuffer handle = 0x%08lx\n", (unsigned long) ctx->shared.hFrameBuffer); return 1;}static void__driHaltFBDev( struct DRIDriverContextRec *ctx ){}struct DRIDriverRec __driDriver = { __driValidateMode, __driValidateMode, __driInitFBDev, __driHaltFBDev};static __GLcontextModes *fbFillInModes( __DRIscreenPrivate *psp, unsigned pixel_bits, unsigned depth_bits, unsigned stencil_bits, GLboolean have_back_buffer ){ __GLcontextModes * modes; __GLcontextModes * m; unsigned num_modes; unsigned depth_buffer_factor; unsigned back_buffer_factor; GLenum fb_format; GLenum fb_type; /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy * enough to add support. Basically, if a context is created with an * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping * will never be used. */ static const GLenum back_buffer_modes[] = { GLX_NONE, GLX_SWAP_UNDEFINED_OML /*, GLX_SWAP_COPY_OML */ }; u_int8_t depth_bits_array[2]; u_int8_t stencil_bits_array[2]; depth_bits_array[0] = depth_bits; depth_bits_array[1] = depth_bits; /* Just like with the accumulation buffer, always provide some modes * with a stencil buffer. It will be a sw fallback, but some apps won't * care about that. */ stencil_bits_array[0] = 0; stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits; depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1; back_buffer_factor = (have_back_buffer) ? 2 : 1; num_modes = depth_buffer_factor * back_buffer_factor * 4; if ( pixel_bits == 16 ) { fb_format = GL_RGB; fb_type = GL_UNSIGNED_SHORT_5_6_5; } else { fb_format = GL_RGBA; fb_type = GL_UNSIGNED_INT_8_8_8_8_REV; } modes = (*psp->contextModes->createContextModes)( num_modes, sizeof( __GLcontextModes ) ); m = modes; if ( ! driFillInModes( & m, fb_format, fb_type, depth_bits_array, stencil_bits_array, depth_buffer_factor, back_buffer_modes, back_buffer_factor, GLX_TRUE_COLOR ) ) { fprintf( stderr, "[%s:%u] Error creating FBConfig!\n", __func__, __LINE__ ); return NULL; } if ( ! driFillInModes( & m, fb_format, fb_type, depth_bits_array, stencil_bits_array, depth_buffer_factor, back_buffer_modes, back_buffer_factor, GLX_DIRECT_COLOR ) ) { fprintf( stderr, "[%s:%u] Error creating FBConfig!\n", __func__, __LINE__ ); return NULL; } /* Mark the visual as slow if there are "fake" stencil bits. */ for ( m = modes ; m != NULL ; m = m->next ) { if ( (m->stencilBits != 0) && (m->stencilBits != stencil_bits) ) { m->visualRating = GLX_SLOW_CONFIG; } } return modes;}/** * This is the bootstrap function for the driver. libGL supplies all of the * requisite information about the system, and the driver initializes itself. * This routine also fills in the linked list pointed to by \c driver_modes * with the \c __GLcontextModes that the driver can support for windows or * pbuffers. * * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on * failure. */PUBLICvoid * __driCreateNewScreen( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc, const __GLcontextModes * modes, const __DRIversion * ddx_version, const __DRIversion * dri_version, const __DRIversion * drm_version, const __DRIframebuffer * frame_buffer, drmAddress pSAREA, int fd, int internal_api_version, __GLcontextModes ** driver_modes ){ __DRIscreenPrivate *psp; static const __DRIversion ddx_expected = { 4, 0, 0 }; static const __DRIversion dri_expected = { 4, 0, 0 }; static const __DRIversion drm_expected = { 1, 5, 0 }; if ( ! driCheckDriDdxDrmVersions2( "fb", dri_version, & dri_expected, ddx_version, & ddx_expected, drm_version, & drm_expected ) ) { return NULL; } psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL, ddx_version, dri_version, drm_version, frame_buffer, pSAREA, fd, internal_api_version, &fbAPI); if ( psp != NULL ) { *driver_modes = fbFillInModes( psp, psp->fbBPP, (psp->fbBPP == 16) ? 16 : 24, (psp->fbBPP == 16) ? 0 : 8, 1); } return (void *) psp;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -