/** * Destroy an Off-Screen Mesa rendering context. * * \param osmesa the context to destroy */ GLAPI void GLAPIENTRY OSMesaDestroyContext( OSMesaContext osmesa ) { if (osmesa) { if (osmesa->rb) _mesa_reference_renderbuffer(&osmesa->rb, NULL); _swsetup_DestroyContext( &osmesa->mesa ); _tnl_DestroyContext( &osmesa->mesa ); _vbo_DestroyContext( &osmesa->mesa ); _swrast_DestroyContext( &osmesa->mesa ); _mesa_destroy_visual( osmesa->gl_visual ); _mesa_unreference_framebuffer( &osmesa->gl_buffer ); _mesa_free_context_data( &osmesa->mesa ); _mesa_free( osmesa ); } }
/** * Set *ptr to point to fb, with refcounting and locking. */ void _mesa_reference_framebuffer(struct gl_framebuffer **ptr, struct gl_framebuffer *fb) { assert(ptr); if (*ptr == fb) { /* no change */ return; } if (*ptr) { _mesa_unreference_framebuffer(ptr); } assert(!*ptr); assert(fb); _glthread_LOCK_MUTEX(fb->Mutex); fb->RefCount++; _glthread_UNLOCK_MUTEX(fb->Mutex); *ptr = fb; }
void GLAPIENTRY _mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers) { GLint i; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); FLUSH_VERTICES(ctx, _NEW_BUFFERS); /* The above doesn't fully flush the drivers in the way that a * glFlush does, but that is required here: */ if (ctx->Driver.Flush) ctx->Driver.Flush(ctx); for (i = 0; i < n; i++) { if (framebuffers[i] > 0) { struct gl_framebuffer *fb; fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]); if (fb) { ASSERT(fb == &DummyFramebuffer || fb->Name == framebuffers[i]); /* check if deleting currently bound framebuffer object */ if (fb == ctx->DrawBuffer) { /* bind default */ ASSERT(fb->RefCount >= 2); _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } /* remove from hash table immediately, to free the ID */ _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]); if (fb != &DummyFramebuffer) { /* But the object will not be freed until it's no longer * bound in any context. */ _mesa_unreference_framebuffer(&fb); } } } } }
static void fbDestroyBuffer(__DRIdrawablePrivate *driDrawPriv) { _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate))); }
/* * Destroy the given FX/Mesa context. */ void GLAPIENTRY fxMesaDestroyContext(fxMesaContext fxMesa) { if (TDFX_DEBUG & VERBOSE_DRIVER) { fprintf(stderr, "fxMesaDestroyContext(...)\n"); } if (!fxMesa) return; if (fxMesa->verbose) { fprintf(stderr, "Misc Stats:\n"); fprintf(stderr, " # swap buffer: %u\n", fxMesa->stats.swapBuffer); if (!fxMesa->stats.swapBuffer) fxMesa->stats.swapBuffer = 1; fprintf(stderr, "Textures Stats:\n"); fprintf(stderr, " Free texture memory on TMU0: %d\n", fxMesa->freeTexMem[FX_TMU0]); if (fxMesa->haveTwoTMUs) fprintf(stderr, " Free texture memory on TMU1: %d\n", fxMesa->freeTexMem[FX_TMU1]); fprintf(stderr, " # request to TMM to upload a texture objects: %u\n", fxMesa->stats.reqTexUpload); fprintf(stderr, " # request to TMM to upload a texture objects per swapbuffer: %.2f\n", fxMesa->stats.reqTexUpload / (float) fxMesa->stats.swapBuffer); fprintf(stderr, " # texture objects uploaded: %u\n", fxMesa->stats.texUpload); fprintf(stderr, " # texture objects uploaded per swapbuffer: %.2f\n", fxMesa->stats.texUpload / (float) fxMesa->stats.swapBuffer); fprintf(stderr, " # MBs uploaded to texture memory: %.2f\n", fxMesa->stats.memTexUpload / (float) (1 << 20)); fprintf(stderr, " # MBs uploaded to texture memory per swapbuffer: %.2f\n", (fxMesa->stats.memTexUpload / (float) fxMesa->stats.swapBuffer) / (float) (1 << 20)); } glbTotNumCtx--; if (!glbTotNumCtx && getenv("MESA_FX_INFO")) { GrSstPerfStats_t st; FX_grSstPerfStats(&st); fprintf(stderr, "Pixels Stats:\n"); fprintf(stderr, " # pixels processed (minus buffer clears): %u\n", (unsigned) st.pixelsIn); fprintf(stderr, " # pixels not drawn due to chroma key test failure: %u\n", (unsigned) st.chromaFail); fprintf(stderr, " # pixels not drawn due to depth test failure: %u\n", (unsigned) st.zFuncFail); fprintf(stderr, " # pixels not drawn due to alpha test failure: %u\n", (unsigned) st.aFuncFail); fprintf(stderr, " # pixels drawn (including buffer clears and LFB writes): %u\n", (unsigned) st.pixelsOut); } /* close the hardware first, * so we can debug atexit problems (memory leaks, etc). */ grSstWinClose(fxMesa->glideContext); fxCloseHardware(); fxDDDestroyFxMesaContext(fxMesa); /* must be before _mesa_destroy_context */ _mesa_destroy_visual(fxMesa->glVis); _mesa_destroy_context(fxMesa->glCtx); _mesa_unreference_framebuffer(&fxMesa->glBuffer); fxTMClose(fxMesa); /* must be after _mesa_destroy_context */ FREE(fxMesa); if (fxMesa == fxMesaCurrentCtx) fxMesaCurrentCtx = NULL; }
/* * Create a new FX/Mesa context and return a handle to it. */ fxMesaContext GLAPIENTRY fxMesaCreateContext(GLuint win, GrScreenResolution_t res, GrScreenRefresh_t ref, const GLint attribList[]) { fxMesaContext fxMesa = NULL; GLcontext *ctx = NULL, *shareCtx = NULL; struct dd_function_table functions; int i; const char *str; int sliaa, numSLI, samplesPerChip; struct SstCard_St *voodoo; struct tdfx_glide *Glide; GLboolean aux; GLboolean doubleBuffer; GLuint colDepth; GLuint depthSize, alphaSize, stencilSize, accumSize; GLuint redBits, greenBits, blueBits, alphaBits; GrPixelFormat_t pixFmt; if (TDFX_DEBUG & VERBOSE_DRIVER) { fprintf(stderr, "fxMesaCreateContext(...)\n"); } /* Okay, first process the user flags */ aux = GL_FALSE; doubleBuffer = GL_FALSE; colDepth = 16; depthSize = alphaSize = stencilSize = accumSize = 0; i = 0; while (attribList[i] != FXMESA_NONE) { switch (attribList[i]) { case FXMESA_COLORDEPTH: colDepth = attribList[++i]; break; case FXMESA_DOUBLEBUFFER: doubleBuffer = GL_TRUE; break; case FXMESA_ALPHA_SIZE: if ((alphaSize = attribList[++i])) { aux = GL_TRUE; } break; case FXMESA_DEPTH_SIZE: if ((depthSize = attribList[++i])) { aux = GL_TRUE; } break; case FXMESA_STENCIL_SIZE: stencilSize = attribList[++i]; break; case FXMESA_ACCUM_SIZE: accumSize = attribList[++i]; break; /* XXX ugly hack here for sharing display lists */ case FXMESA_SHARE_CONTEXT: shareCtx = (GLcontext *)attribList[++i]; break; default: fprintf(stderr, "fxMesaCreateContext: ERROR: wrong parameter (%d) passed\n", attribList[i]); return NULL; } i++; } if (!fxQueryHardware()) { str = "no Voodoo hardware!"; goto errorhandler; } grSstSelect(glbCurrentBoard); /*grEnable(GR_OPENGL_MODE_EXT);*/ /* [koolsmoky] */ voodoo = &glbHWConfig.SSTs[glbCurrentBoard]; fxMesa = (fxMesaContext)CALLOC_STRUCT(tfxMesaContext); if (!fxMesa) { str = "private context"; goto errorhandler; } if (getenv("MESA_FX_INFO")) { fxMesa->verbose = GL_TRUE; } fxMesa->type = voodoo->type; fxMesa->HavePalExt = voodoo->HavePalExt && !getenv("MESA_FX_IGNORE_PALEXT"); fxMesa->HavePixExt = voodoo->HavePixExt && !getenv("MESA_FX_IGNORE_PIXEXT"); fxMesa->HaveTexFmt = voodoo->HaveTexFmt && !getenv("MESA_FX_IGNORE_TEXFMT"); fxMesa->HaveCmbExt = voodoo->HaveCmbExt && !getenv("MESA_FX_IGNORE_CMBEXT"); fxMesa->HaveMirExt = voodoo->HaveMirExt && !getenv("MESA_FX_IGNORE_MIREXT"); fxMesa->HaveTexUma = voodoo->HaveTexUma && !getenv("MESA_FX_IGNORE_TEXUMA"); fxMesa->Glide = glbHWConfig.Glide; Glide = &fxMesa->Glide; fxMesa->HaveTexus2 = Glide->txImgQuantize && Glide->txMipQuantize && Glide->txPalToNcc && !getenv("MESA_FX_IGNORE_TEXUS2"); /* Determine if we need vertex swapping, RGB order and SLI/AA */ sliaa = 0; switch (fxMesa->type) { case GR_SSTTYPE_VOODOO: case GR_SSTTYPE_SST96: case GR_SSTTYPE_Banshee: fxMesa->bgrOrder = GL_TRUE; fxMesa->snapVertices = (getenv("MESA_FX_NOSNAP") == NULL); break; case GR_SSTTYPE_Voodoo2: fxMesa->bgrOrder = GL_TRUE; fxMesa->snapVertices = GL_FALSE; break; case GR_SSTTYPE_Voodoo4: case GR_SSTTYPE_Voodoo5: /* number of SLI units and AA Samples per chip */ if ((str = Glide->grGetRegistryOrEnvironmentStringExt("SSTH3_SLI_AA_CONFIGURATION")) != NULL) { sliaa = atoi(str); } case GR_SSTTYPE_Voodoo3: default: fxMesa->bgrOrder = GL_FALSE; fxMesa->snapVertices = GL_FALSE; break; } /* XXX todo - Add the old SLI/AA settings for Napalm. */ switch(voodoo->numChips) { case 4: /* 4 chips */ switch(sliaa) { case 8: /* 8 Sample AA */ numSLI = 1; samplesPerChip = 2; break; case 7: /* 4 Sample AA */ numSLI = 1; samplesPerChip = 1; break; case 6: /* 2 Sample AA */ numSLI = 2; samplesPerChip = 1; break; default: numSLI = 4; samplesPerChip = 1; } break; case 2: /* 2 chips */ switch(sliaa) { case 4: /* 4 Sample AA */ numSLI = 1; samplesPerChip = 2; break; case 3: /* 2 Sample AA */ numSLI = 1; samplesPerChip = 1; break; default: numSLI = 2; samplesPerChip = 1; } break; default: /* 1 chip */ switch(sliaa) { case 1: /* 2 Sample AA */ numSLI = 1; samplesPerChip = 2; break; default: numSLI = 1; samplesPerChip = 1; } } fxMesa->fsaa = samplesPerChip * voodoo->numChips / numSLI; /* 1:noFSAA, 2:2xFSAA, 4:4xFSAA, 8:8xFSAA */ switch (fxMesa->colDepth = colDepth) { case 15: redBits = 5; greenBits = 5; blueBits = 5; alphaBits = depthSize ? 1 : 8; switch(fxMesa->fsaa) { case 8: pixFmt = GR_PIXFMT_AA_8_ARGB_1555; break; case 4: pixFmt = GR_PIXFMT_AA_4_ARGB_1555; break; case 2: pixFmt = GR_PIXFMT_AA_2_ARGB_1555; break; default: pixFmt = GR_PIXFMT_ARGB_1555; } break; case 16: redBits = 5; greenBits = 6; blueBits = 5; alphaBits = depthSize ? 0 : 8; switch(fxMesa->fsaa) { case 8: pixFmt = GR_PIXFMT_AA_8_RGB_565; break; case 4: pixFmt = GR_PIXFMT_AA_4_RGB_565; break; case 2: pixFmt = GR_PIXFMT_AA_2_RGB_565; break; default: pixFmt = GR_PIXFMT_RGB_565; } break; case 24: fxMesa->colDepth = 32; case 32: redBits = 8; greenBits = 8; blueBits = 8; alphaBits = 8; switch(fxMesa->fsaa) { case 8: pixFmt = GR_PIXFMT_AA_8_ARGB_8888; break; case 4: pixFmt = GR_PIXFMT_AA_4_ARGB_8888; break; case 2: pixFmt = GR_PIXFMT_AA_2_ARGB_8888; break; default: pixFmt = GR_PIXFMT_ARGB_8888; } break; default: str = "pixelFormat"; goto errorhandler; } /* Tips: * 1. we don't bother setting/checking AUX for stencil, because we'll decide * later whether we have HW stencil, based on depth buffer (thus AUX is * properly set) * 2. when both DEPTH and ALPHA are enabled, depth should win. However, it is * not clear whether 15bpp and 32bpp require AUX alpha buffer. Furthermore, * alpha buffering is required only if destination alpha is used in alpha * blending; alpha blending modes that do not use destination alpha can be * used w/o alpha buffer. * 3. `alphaBits' is what we can provide * `alphaSize' is what app requests * if we cannot provide enough bits for alpha buffer, we should fallback to * SW alpha. However, setting `alphaBits' to `alphaSize' might confuse some * of the span functions... */ fxMesa->haveHwAlpha = GL_FALSE; if (alphaSize && (alphaSize <= alphaBits)) { alphaSize = alphaBits; fxMesa->haveHwAlpha = GL_TRUE; } fxMesa->haveHwStencil = (fxMesa->HavePixExt && stencilSize && depthSize == 24); fxMesa->haveZBuffer = depthSize > 0; fxMesa->haveDoubleBuffer = doubleBuffer; fxMesa->haveGlobalPaletteTexture = GL_FALSE; fxMesa->board = glbCurrentBoard; fxMesa->haveTwoTMUs = (voodoo->nTexelfx > 1); if ((str = Glide->grGetRegistryOrEnvironmentStringExt("FX_GLIDE_NUM_TMU"))) { if (atoi(str) <= 1) { fxMesa->haveTwoTMUs = GL_FALSE; } } if ((str = Glide->grGetRegistryOrEnvironmentStringExt("FX_GLIDE_SWAPPENDINGCOUNT"))) { fxMesa->maxPendingSwapBuffers = atoi(str); if (fxMesa->maxPendingSwapBuffers > 6) { fxMesa->maxPendingSwapBuffers = 6; } else if (fxMesa->maxPendingSwapBuffers < 0) { fxMesa->maxPendingSwapBuffers = 0; } } else { fxMesa->maxPendingSwapBuffers = 2; } if ((str = Glide->grGetRegistryOrEnvironmentStringExt("FX_GLIDE_SWAPINTERVAL"))) { fxMesa->swapInterval = atoi(str); } else { fxMesa->swapInterval = 0; } BEGIN_BOARD_LOCK(); if (fxMesa->HavePixExt) { fxMesa->glideContext = Glide->grSstWinOpenExt((FxU32)win, res, ref, GR_COLORFORMAT_ABGR, GR_ORIGIN_LOWER_LEFT, pixFmt, 2, aux); } else if (pixFmt == GR_PIXFMT_RGB_565) { fxMesa->glideContext = grSstWinOpen((FxU32)win, res, ref, GR_COLORFORMAT_ABGR, GR_ORIGIN_LOWER_LEFT, 2, aux); } else { fxMesa->glideContext = 0; } END_BOARD_LOCK(); if (!fxMesa->glideContext) { str = "grSstWinOpen"; goto errorhandler; } /* screen */ fxMesa->screen_width = FX_grSstScreenWidth(); fxMesa->screen_height = FX_grSstScreenHeight(); /* window inside screen */ fxMesa->width = fxMesa->screen_width; fxMesa->height = fxMesa->screen_height; /* scissor inside window */ fxMesa->clipMinX = 0; fxMesa->clipMaxX = fxMesa->width; fxMesa->clipMinY = 0; fxMesa->clipMaxY = fxMesa->height; if (fxMesa->verbose) { FxI32 tmuRam, fbRam; /* Not that it matters, but tmuRam and fbRam change after grSstWinOpen. */ tmuRam = voodoo->tmuConfig[GR_TMU0].tmuRam; fbRam = voodoo->fbRam; BEGIN_BOARD_LOCK(); grGet(GR_MEMORY_TMU, 4, &tmuRam); grGet(GR_MEMORY_FB, 4, &fbRam); END_BOARD_LOCK(); fprintf(stderr, "Voodoo Using Glide %s\n", grGetString(GR_VERSION)); fprintf(stderr, "Voodoo Board: %d/%d, %s, %d GPU\n", fxMesa->board + 1, glbHWConfig.num_sst, grGetString(GR_HARDWARE), voodoo->numChips); fprintf(stderr, "Voodoo Memory: FB = %ld, TM = %d x %ld\n", fbRam, voodoo->nTexelfx, tmuRam); fprintf(stderr, "Voodoo Screen: %dx%d:%d %s, %svertex snapping\n", fxMesa->screen_width, fxMesa->screen_height, colDepth, fxMesa->bgrOrder ? "BGR" : "RGB", fxMesa->snapVertices ? "" : "no "); } sprintf(fxMesa->rendererString, "Mesa %s v0.63 %s%s", grGetString(GR_RENDERER), grGetString(GR_HARDWARE), ((fxMesa->type < GR_SSTTYPE_Voodoo4) && (voodoo->numChips > 1)) ? " SLI" : ""); fxMesa->glVis = _mesa_create_visual(GL_TRUE, /* RGB mode */ doubleBuffer, GL_FALSE, /* stereo */ redBits, /* RGBA.R bits */ greenBits, /* RGBA.G bits */ blueBits, /* RGBA.B bits */ alphaSize, /* RGBA.A bits */ 0, /* index bits */ depthSize, /* depth_size */ stencilSize, /* stencil_size */ accumSize, accumSize, accumSize, alphaSize ? accumSize : 0, 1); if (!fxMesa->glVis) { str = "_mesa_create_visual"; goto errorhandler; } _mesa_init_driver_functions(&functions); ctx = fxMesa->glCtx = _mesa_create_context(fxMesa->glVis, shareCtx, &functions, (void *) fxMesa); if (!ctx) { str = "_mesa_create_context"; goto errorhandler; } if (!fxDDInitFxMesaContext(fxMesa)) { str = "fxDDInitFxMesaContext"; goto errorhandler; } fxMesa->glBuffer = _mesa_create_framebuffer(fxMesa->glVis); #if 0 /* XXX this is a complete mess :( * _mesa_add_soft_renderbuffers * driNewRenderbuffer */ GL_FALSE, /* no software depth */ stencilSize && !fxMesa->haveHwStencil, fxMesa->glVis->accumRedBits > 0, alphaSize && !fxMesa->haveHwAlpha); #endif if (!fxMesa->glBuffer) { str = "_mesa_create_framebuffer"; goto errorhandler; } glbTotNumCtx++; /* install signal handlers */ #if defined(__linux__) /* Only install if environment var. is not set. */ if (!getenv("MESA_FX_NO_SIGNALS")) { signal(SIGINT, cleangraphics_handler); signal(SIGHUP, cleangraphics_handler); signal(SIGPIPE, cleangraphics_handler); signal(SIGFPE, cleangraphics_handler); signal(SIGBUS, cleangraphics_handler); signal(SIGILL, cleangraphics_handler); signal(SIGSEGV, cleangraphics_handler); signal(SIGTERM, cleangraphics_handler); } #endif return fxMesa; errorhandler: if (fxMesa) { if (fxMesa->glideContext) { grSstWinClose(fxMesa->glideContext); fxMesa->glideContext = 0; } if (fxMesa->state) { FREE(fxMesa->state); } if (fxMesa->fogTable) { FREE(fxMesa->fogTable); } if (fxMesa->glBuffer) { _mesa_unreference_framebuffer(&fxMesa->glBuffer); } if (fxMesa->glVis) { _mesa_destroy_visual(fxMesa->glVis); } if (fxMesa->glCtx) { _mesa_destroy_context(fxMesa->glCtx); } FREE(fxMesa); } fprintf(stderr, "fxMesaCreateContext: ERROR: %s\n", str); return NULL; }