/** * Bind an OSMesaContext to an image buffer. The image buffer is just a * block of memory which the client provides. Its size must be at least * as large as width*height*sizeof(type). Its address should be a multiple * of 4 if using RGBA mode. * * Image data is stored in the order of glDrawPixels: row-major order * with the lower-left image pixel stored in the first array position * (ie. bottom-to-top). * * If the context's viewport hasn't been initialized yet, it will now be * initialized to (0,0,width,height). * * Input: osmesa - the rendering context * buffer - the image buffer memory * type - data type for pixel components * Normally, only GL_UNSIGNED_BYTE and GL_UNSIGNED_SHORT_5_6_5 * are supported. But if Mesa's been compiled with CHAN_BITS==16 * then type may be GL_UNSIGNED_SHORT or GL_UNSIGNED_BYTE. And if * Mesa's been build with CHAN_BITS==32 then type may be GL_FLOAT, * GL_UNSIGNED_SHORT or GL_UNSIGNED_BYTE. * width, height - size of image buffer in pixels, at least 1 * Return: GL_TRUE if success, GL_FALSE if error because of invalid osmesa, * invalid buffer address, invalid type, width<1, height<1, * width>internal limit or height>internal limit. */ GLAPI GLboolean GLAPIENTRY OSMesaMakeCurrent( OSMesaContext osmesa, void *buffer, GLenum type, GLsizei width, GLsizei height ) { if (!osmesa || !buffer || width < 1 || height < 1 || width > SWRAST_MAX_WIDTH || height > SWRAST_MAX_HEIGHT) { return GL_FALSE; } if (osmesa->format == OSMESA_RGB_565 && type != GL_UNSIGNED_SHORT_5_6_5) { return GL_FALSE; } #if 0 if (!(type == GL_UNSIGNED_BYTE || (type == GL_UNSIGNED_SHORT && CHAN_BITS >= 16) || (type == GL_FLOAT && CHAN_BITS == 32))) { /* i.e. is sizeof(type) * 8 > CHAN_BITS? */ return GL_FALSE; } #endif osmesa_update_state( &osmesa->mesa, 0 ); /* Call this periodically to detect when the user has begun using * GL rendering from multiple threads. */ _glapi_check_multithread(); /* Create a front/left color buffer which wraps the user-provided buffer. * There is no back color buffer. * If the user tries to use a 8, 16 or 32-bit/channel buffer that * doesn't match what Mesa was compiled for (CHAN_BITS) the * _mesa_add_renderbuffer() function will create a "wrapper" renderbuffer * that converts rendering from CHAN_BITS to the user-requested channel * size. */ if (!osmesa->srb) { osmesa->srb = new_osmesa_renderbuffer(&osmesa->mesa, osmesa->format, type); _mesa_remove_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT); _mesa_add_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT, &osmesa->srb->Base); assert(osmesa->srb->Base.RefCount == 2); } osmesa->DataType = type; /* Set renderbuffer fields. Set width/height = 0 to force * osmesa_renderbuffer_storage() being called by _mesa_resize_framebuffer() */ osmesa->srb->Buffer = buffer; osmesa->srb->Base.Width = osmesa->srb->Base.Height = 0; /* Set the framebuffer's size. This causes the * osmesa_renderbuffer_storage() function to get called. */ _mesa_resize_framebuffer(&osmesa->mesa, osmesa->gl_buffer, width, height); _mesa_make_current( &osmesa->mesa, osmesa->gl_buffer, osmesa->gl_buffer ); /* Remove renderbuffer attachment, then re-add. This installs the * renderbuffer adaptor/wrapper if needed (for bpp conversion). */ _mesa_remove_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT); _mesa_add_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT, &osmesa->srb->Base); /* this updates the visual's red/green/blue/alphaBits fields */ _mesa_update_framebuffer_visual(&osmesa->mesa, osmesa->gl_buffer); /* update the framebuffer size */ _mesa_resize_framebuffer(&osmesa->mesa, osmesa->gl_buffer, width, height); return GL_TRUE; }
/** * Make a particular context current. * * \note This is in this file so that it can access dummyContext. */ static Bool MakeContextCurrent(Display * dpy, GLXDrawable draw, GLXDrawable read, GLXContext gc_user) { struct glx_context *gc = (struct glx_context *) gc_user; struct glx_context *oldGC = __glXGetCurrentContext(); /* XXX: If this is left out, then libGL ends up not having this * symbol, and drivers using it fail to load. Compare the * implementation of this symbol to _glapi_noop_enable_warnings(), * though, which gets into the library despite no callers, the same * prototypes, and the same compile flags to the files containing * them. Moving the definition to glapi_nop.c gets it into the * library, though. */ (void)_glthread_GetID(); /* Make sure that the new context has a nonzero ID. In the request, * a zero context ID is used only to mean that we bind to no current * context. */ if ((gc != NULL) && (gc->xid == None)) { return GL_FALSE; } if (gc == NULL && (draw != None || read != None)) { __glXGenerateError(dpy, (draw != None) ? draw : read, BadMatch, X_GLXMakeContextCurrent); return False; } if (gc != NULL && (draw == None || read == None)) { __glXGenerateError(dpy, None, BadMatch, X_GLXMakeContextCurrent); return False; } _glapi_check_multithread(); __glXLock(); if (oldGC == gc && gc->currentDrawable == draw && gc->currentReadable == read) { __glXUnlock(); return True; } if (oldGC != &dummyContext) { if (--oldGC->thread_refcount == 0) { oldGC->vtable->unbind(oldGC, gc); oldGC->currentDpy = 0; } } if (gc) { /* Attempt to bind the context. We do this before mucking with * gc and __glXSetCurrentContext to properly handle our state in * case of an error. * * If an error occurs, set the Null context since we've already * blown away our old context. The caller is responsible for * figuring out how to handle setting a valid context. */ if (gc->vtable->bind(gc, oldGC, draw, read) != Success) { __glXSetCurrentContextNull(); __glXUnlock(); __glXGenerateError(dpy, None, GLXBadContext, X_GLXMakeContextCurrent); return GL_FALSE; } if (gc->thread_refcount == 0) { gc->currentDpy = dpy; gc->currentDrawable = draw; gc->currentReadable = read; } gc->thread_refcount++; __glXSetCurrentContext(gc); } else { __glXSetCurrentContextNull(); } if (oldGC->thread_refcount == 0 && oldGC != &dummyContext && oldGC->xid == None) { /* We are switching away from a context that was * previously destroyed, so we need to free the memory * for the old handle. */ oldGC->vtable->destroy(oldGC); } __glXUnlock(); return GL_TRUE; }
/** * Make a particular context current. * * \note This is in this file so that it can access dummyContext. */ static Bool MakeContextCurrent(Display * dpy, GLXDrawable draw, GLXDrawable read, GLXContext gc_user) { struct glx_context *gc = (struct glx_context *) gc_user; struct glx_context *oldGC = __glXGetCurrentContext(); /* Make sure that the new context has a nonzero ID. In the request, * a zero context ID is used only to mean that we bind to no current * context. */ if ((gc != NULL) && (gc->xid == None)) { return GL_FALSE; } _glapi_check_multithread(); __glXLock(); if (oldGC == gc && gc->currentDrawable == draw && gc->currentReadable == read) { __glXUnlock(); return True; } if (oldGC != &dummyContext) { if (--oldGC->thread_refcount == 0) { oldGC->vtable->unbind(oldGC, gc); oldGC->currentDpy = 0; } } if (gc) { /* Attempt to bind the context. We do this before mucking with * gc and __glXSetCurrentContext to properly handle our state in * case of an error. * * If an error occurs, set the Null context since we've already * blown away our old context. The caller is responsible for * figuring out how to handle setting a valid context. */ if (gc->vtable->bind(gc, oldGC, draw, read) != Success) { __glXSetCurrentContextNull(); __glXUnlock(); __glXGenerateError(dpy, None, GLXBadContext, X_GLXMakeContextCurrent); return GL_FALSE; } if (gc->thread_refcount == 0) { gc->currentDpy = dpy; gc->currentDrawable = draw; gc->currentReadable = read; } gc->thread_refcount++; __glXSetCurrentContext(gc); } else { __glXSetCurrentContextNull(); } if (oldGC->thread_refcount == 0 && oldGC != &dummyContext && oldGC->xid == None) { /* We are switching away from a context that was * previously destroyed, so we need to free the memory * for the old handle. */ oldGC->vtable->destroy(oldGC); } __glXUnlock(); return GL_TRUE; }