Exemplo n.º 1
0
/**
 * 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;
}
Exemplo n.º 2
0
/**
 * 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;
}
Exemplo n.º 3
0
/**
 * 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;
}