[Mesa-dev] [PATCH 2/7] st/osmesa: new OSMesa gallium state tracker

Jose Fonseca jfonseca at vmware.com
Tue Mar 12 17:10:53 PDT 2013


This patch has some #if 0000 near the end. It's not clear if it should be removed or completed.

Otherwise the series looks good AFAICT.

Jose

----- Original Message -----
> ---
>  src/gallium/state_trackers/osmesa/osmesa.c |  828
>  ++++++++++++++++++++++++++++
>  1 files changed, 828 insertions(+), 0 deletions(-)
>  create mode 100644 src/gallium/state_trackers/osmesa/osmesa.c
> 
> diff --git a/src/gallium/state_trackers/osmesa/osmesa.c
> b/src/gallium/state_trackers/osmesa/osmesa.c
> new file mode 100644
> index 0000000..fafcf19
> --- /dev/null
> +++ b/src/gallium/state_trackers/osmesa/osmesa.c
> @@ -0,0 +1,828 @@
> +/*
> + * Copyright (c) 2013  Brian Paul   All Rights Reserved.
> + *
> + * 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.
> + */
> +
> +
> +/*
> + * Off-Screen rendering into client memory.
> + * State tracker for gallium (for softpipe and llvmpipe)
> + *
> + * Notes:
> + *
> + * If Gallium is built with LLVM support we use the llvmpipe driver.
> + * Otherwise we use softpipe.  The GALLIUM_DRIVER environment variable
> + * may be set to "softpipe" or "llvmpipe" to override.
> + *
> + * With softpipe we could render directly into the user's buffer by using a
> + * display target resource.  However, softpipe doesn't suport "upside-down"
> + * rendering which would be needed for the OSMESA_Y_UP=TRUE case.
> + *
> + * With llvmpipe we could only render directly into the user's buffer when
> its
> + * width and height is a multiple of the tile size (64 pixels).
> + *
> + * Because of these constraints we always render into ordinary resources
> then
> + * copy the results to the user's buffer in the flush_front() function which
> + * is called when the app calls glFlush/Finish.
> + *
> + * In general, the OSMesa interface is pretty ugly and not a good match
> + * for Gallium.  But we're interested in doing the best we can to preserve
> + * application portability.  With a little work we could come up with a
> + * much nicer, new off-screen Gallium interface...
> + */
> +
> +
> +#include "GL/osmesa.h"
> +
> +#include "glapi/glapi.h"  /* for OSMesaGetProcAddress below */
> +
> +#include "pipe/p_context.h"
> +#include "pipe/p_screen.h"
> +#include "pipe/p_state.h"
> +
> +#include "util/u_atomic.h"
> +#include "util/u_box.h"
> +#include "util/u_format.h"
> +#include "util/u_memory.h"
> +
> +#include "state_tracker/st_api.h"
> +#include "state_tracker/st_gl_api.h"
> +
> +
> +
> +extern struct pipe_screen *
> +osmesa_create_screen(void);
> +
> +
> +
> +struct osmesa_buffer
> +{
> +   struct st_framebuffer_iface *stfb;
> +   struct st_visual visual;
> +   unsigned width, height;
> +
> +   struct pipe_resource *textures[ST_ATTACHMENT_COUNT];
> +
> +   void *map;
> +};
> +
> +
> +struct osmesa_context
> +{
> +   struct st_context_iface *stctx;
> +
> +   struct osmesa_buffer *current_buffer;
> +
> +   enum pipe_format depth_stencil_format, accum_format;
> +
> +   GLenum format;         /*< User-specified context format */
> +   GLenum type;           /*< Buffer's data type */
> +   GLint user_row_length; /*< user-specified number of pixels per row */
> +   GLboolean y_up;        /*< TRUE  -> Y increases upward */
> +                          /*< FALSE -> Y increases downward */
> +};
> +
> +
> +
> +/**
> + * Called from the ST manager.
> + */
> +static int
> +osmesa_st_get_param(struct st_manager *smapi, enum st_manager_param param)
> +{
> +   /* no-op */
> +   return 0;
> +}
> +
> +
> +/**
> + * Create/return singleton st_api object.
> + */
> +static struct st_api *
> +get_st_api(void)
> +{
> +   static struct st_api *stapi = NULL;
> +   if (!stapi) {
> +      stapi = st_gl_api_create();
> +   }
> +   return stapi;
> +}
> +
> +
> +/**
> + * Create/return a singleton st_manager object.
> + */
> +static struct st_manager *
> +get_st_manager(void)
> +{
> +   static struct st_manager *stmgr = NULL;
> +   if (!stmgr) {
> +      stmgr = CALLOC_STRUCT(st_manager);
> +      if (stmgr) {
> +         stmgr->screen = osmesa_create_screen();
> +         stmgr->get_param = osmesa_st_get_param;
> +         stmgr->get_egl_image = NULL;
> +      }
> +   }
> +   return stmgr;
> +}
> +
> +
> +static INLINE boolean
> +little_endian(void)
> +{
> +   const unsigned ui = 1;
> +   return *((const char *) &ui);
> +}
> +
> +
> +/**
> + * Given an OSMESA_x format and a GL_y type, return the best
> + * matching PIPE_FORMAT_z.
> + * Note that we can't exactly match all user format/type combinations
> + * with gallium formats.  If we find this to be a problem, we can
> + * implement more elaborate format/type conversion in the flush_front()
> + * function.
> + */
> +static enum pipe_format
> +osmesa_choose_format(GLenum format, GLenum type)
> +{
> +   switch (format) {
> +   case OSMESA_RGBA:
> +      if (type == GL_UNSIGNED_BYTE) {
> +         if (little_endian())
> +            return PIPE_FORMAT_R8G8B8A8_UNORM;
> +         else
> +            return PIPE_FORMAT_A8B8G8R8_UNORM;
> +      }
> +      else if (type == GL_UNSIGNED_SHORT) {
> +         return PIPE_FORMAT_R16G16B16A16_UNORM;
> +      }
> +      else if (type == GL_FLOAT) {
> +         return PIPE_FORMAT_R32G32B32A32_FLOAT;
> +      }
> +      else {
> +         return PIPE_FORMAT_NONE;
> +      }
> +      break;
> +   case OSMESA_BGRA:
> +      if (type == GL_UNSIGNED_BYTE) {
> +         if (little_endian())
> +            return PIPE_FORMAT_B8G8R8A8_UNORM;
> +         else
> +            return PIPE_FORMAT_A8R8G8B8_UNORM;
> +      }
> +      else if (type == GL_UNSIGNED_SHORT) {
> +         return PIPE_FORMAT_R16G16B16A16_UNORM;
> +      }
> +      else if (type == GL_FLOAT) {
> +         return PIPE_FORMAT_R32G32B32A32_FLOAT;
> +      }
> +      else {
> +         return PIPE_FORMAT_NONE;
> +      }
> +      break;
> +   case OSMESA_ARGB:
> +      if (type == GL_UNSIGNED_BYTE) {
> +         if (little_endian())
> +            return PIPE_FORMAT_A8R8G8B8_UNORM;
> +         else
> +            return PIPE_FORMAT_B8G8R8A8_UNORM;
> +      }
> +      else if (type == GL_UNSIGNED_SHORT) {
> +         return PIPE_FORMAT_R16G16B16A16_UNORM;
> +      }
> +      else if (type == GL_FLOAT) {
> +         return PIPE_FORMAT_R32G32B32A32_FLOAT;
> +      }
> +      else {
> +         return PIPE_FORMAT_NONE;
> +      }
> +      break;
> +   case OSMESA_RGB:
> +      if (type == GL_UNSIGNED_BYTE) {
> +         return PIPE_FORMAT_R8G8B8_UNORM;
> +      }
> +      else if (type == GL_UNSIGNED_SHORT) {
> +         return PIPE_FORMAT_R16G16B16_UNORM;
> +      }
> +      else if (type == GL_FLOAT) {
> +         return PIPE_FORMAT_R32G32B32_FLOAT;
> +      }
> +      else {
> +         return PIPE_FORMAT_NONE;
> +      }
> +      break;
> +   case OSMESA_BGR:
> +      /* No gallium format for this one */
> +      return PIPE_FORMAT_NONE;
> +   case OSMESA_RGB_565:
> +      return PIPE_FORMAT_B5G6R5_UNORM;
> +   default:
> +      ; /* fall-through */
> +   }
> +   return PIPE_FORMAT_NONE;
> +}
> +
> +
> +/**
> + * Initialize an st_visual object.
> + */
> +static void
> +osmesa_init_st_visual(struct st_visual *vis,
> +                      enum pipe_format color_format,
> +                      enum pipe_format ds_format,
> +                      enum pipe_format accum_format)
> +{
> +   vis->buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK;
> +   vis->color_format = color_format;
> +   vis->depth_stencil_format = ds_format;
> +   vis->accum_format = accum_format;
> +   vis->samples = 1;
> +   vis->render_buffer = ST_ATTACHMENT_FRONT_LEFT;
> +}
> +
> +
> +/**
> + * Return the osmesa_buffer that corresponds to an st_framebuffer_iface.
> + */
> +static INLINE struct osmesa_buffer *
> +stfbi_to_osbuffer(struct st_framebuffer_iface *stfbi)
> +{
> +   return (struct osmesa_buffer *) stfbi->st_manager_private;
> +}
> +
> +
> +/**
> + * Called via glFlush/glFinish.  This is where we copy the contents
> + * of the driver's color buffer into the user-specified buffer.
> + */
> +static boolean
> +osmesa_st_framebuffer_flush_front(struct st_context_iface *stctx,
> +                                  struct st_framebuffer_iface *stfbi,
> +                                  enum st_attachment_type statt)
> +{
> +   OSMesaContext osmesa = OSMesaGetCurrentContext();
> +   struct osmesa_buffer *osbuffer = stfbi_to_osbuffer(stfbi);
> +   struct pipe_context *pipe = stctx->pipe;
> +   struct pipe_resource *res = osbuffer->textures[statt];
> +   struct pipe_transfer *transfer = NULL;
> +   struct pipe_box box;
> +   void *map;
> +   ubyte *src, *dst;
> +   unsigned y, bytes, bpp;
> +   int dst_stride;
> +
> +   u_box_2d(0, 0, res->width0, res->height0, &box);
> +
> +   map = pipe->transfer_map(pipe, res, 0, PIPE_TRANSFER_READ, &box,
> +                            &transfer);
> +
> +   /*
> +    * Copy the color buffer from the resource to the user's buffer.
> +    */
> +   bpp = util_format_get_blocksize(osbuffer->visual.color_format);
> +   src = map;
> +   dst = osbuffer->map;
> +   if (osmesa->user_row_length)
> +      dst_stride = bpp * osmesa->user_row_length;
> +   else
> +      dst_stride = bpp * osbuffer->width;
> +   bytes = bpp * res->width0;
> +
> +   if (osmesa->y_up) {
> +      /* need to flip image upside down */
> +      dst = dst + (res->height0 - 1) * dst_stride;
> +      dst_stride = -dst_stride;
> +   }
> +
> +   for (y = 0; y < res->height0; y++) {
> +      memcpy(dst, src, bytes);
> +      dst += dst_stride;
> +      src += transfer->stride;
> +   }
> +
> +   pipe->transfer_unmap(pipe, transfer);
> +
> +   return TRUE;
> +}
> +
> +
> +/**
> + * Called by the st manager to validate the framebuffer (allocate
> + * its resources).
> + */
> +static boolean
> +osmesa_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
> +                               const enum st_attachment_type *statts,
> +                               unsigned count,
> +                               struct pipe_resource **out)
> +{
> +   struct pipe_screen *screen = get_st_manager()->screen;
> +   enum st_attachment_type i;
> +   struct osmesa_buffer *osbuffer = stfbi_to_osbuffer(stfbi);
> +   struct pipe_resource templat;
> +
> +   memset(&templat, 0, sizeof(templat));
> +   templat.target = PIPE_TEXTURE_RECT;
> +   templat.format = 0; /* setup below */
> +   templat.last_level = 0;
> +   templat.width0 = osbuffer->width;
> +   templat.height0 = osbuffer->height;
> +   templat.depth0 = 1;
> +   templat.array_size = 1;
> +   templat.usage = PIPE_USAGE_DEFAULT;
> +   templat.bind = 0; /* setup below */
> +   templat.flags = 0;
> +
> +   for (i = 0; i < count; i++) {
> +      enum pipe_format format;
> +      unsigned bind;
> +
> +      /*
> +       * At this time, we really only need to handle the front-left color
> +       * attachment, since that's all we specified for the visual in
> +       * osmesa_init_st_visual().
> +       */
> +      if (statts[i] == ST_ATTACHMENT_FRONT_LEFT) {
> +         format = osbuffer->visual.color_format;
> +         bind = PIPE_BIND_RENDER_TARGET;
> +      }
> +      else if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) {
> +         format = osbuffer->visual.depth_stencil_format;
> +         bind = PIPE_BIND_DEPTH_STENCIL;
> +      }
> +      else if (statts[i] == ST_ATTACHMENT_ACCUM) {
> +         format = osbuffer->visual.accum_format;
> +         bind = PIPE_BIND_RENDER_TARGET;
> +      }
> +
> +      templat.format = format;
> +      templat.bind = bind;
> +      out[i] = osbuffer->textures[i] =
> +         screen->resource_create(screen, &templat);
> +   }
> +
> +   return TRUE;
> +}
> +
> +
> +static struct st_framebuffer_iface *
> +osmesa_create_st_framebuffer(void)
> +{
> +   struct st_framebuffer_iface *stfbi = CALLOC_STRUCT(st_framebuffer_iface);
> +   if (stfbi) {
> +      stfbi->flush_front = osmesa_st_framebuffer_flush_front;
> +      stfbi->validate = osmesa_st_framebuffer_validate;
> +      p_atomic_set(&stfbi->stamp, 1);
> +   }
> +   return stfbi;
> +}
> +
> +
> +static struct osmesa_buffer *
> +osmesa_create_buffer(enum pipe_format color_format,
> +                     enum pipe_format ds_format,
> +                     enum pipe_format accum_format)
> +{
> +   struct osmesa_buffer *osbuffer = CALLOC_STRUCT(osmesa_buffer);
> +   if (osbuffer) {
> +      osbuffer->stfb = osmesa_create_st_framebuffer();
> +
> +      osbuffer->stfb->st_manager_private = osbuffer;
> +      osbuffer->stfb->visual = &osbuffer->visual;
> +
> +      osmesa_init_st_visual(&osbuffer->visual, color_format,
> +                            ds_format, accum_format);
> +   }
> +   return osbuffer;
> +}
> +
> +
> +static void
> +osmesa_destroy_buffer(struct osmesa_buffer *osbuffer)
> +{
> +   FREE(osbuffer->stfb);
> +   FREE(osbuffer);
> +}
> +
> +
> +
> +/**********************************************************************/
> +/*****                    Public Functions                        *****/
> +/**********************************************************************/
> +
> +
> +/**
> + * Create an Off-Screen Mesa rendering context.  The only attribute needed
> is
> + * an RGBA vs Color-Index mode flag.
> + *
> + * Input:  format - Must be GL_RGBA
> + *         sharelist - specifies another OSMesaContext with which to share
> + *                     display lists.  NULL indicates no sharing.
> + * Return:  an OSMesaContext or 0 if error
> + */
> +GLAPI OSMesaContext GLAPIENTRY
> +OSMesaCreateContext(GLenum format, OSMesaContext sharelist)
> +{
> +   return OSMesaCreateContextExt(format, 24, 8, 0, sharelist);
> +}
> +
> +
> +/**
> + * New in Mesa 3.5
> + *
> + * Create context and specify size of ancillary buffers.
> + */
> +GLAPI OSMesaContext GLAPIENTRY
> +OSMesaCreateContextExt(GLenum format, GLint depthBits, GLint stencilBits,
> +                       GLint accumBits, OSMesaContext sharelist)
> +{
> +   OSMesaContext osmesa;
> +   struct st_context_iface *st_shared;
> +   enum st_context_error st_error = 0;
> +   struct st_context_attribs attribs;
> +   struct st_api *stapi = get_st_api();
> +
> +   if (sharelist) {
> +      st_shared = sharelist->stctx;
> +   }
> +   else {
> +      st_shared = NULL;
> +   }
> +
> +   osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context);
> +   if (!osmesa)
> +      return NULL;
> +
> +   /* Choose depth/stencil/accum buffer formats */
> +   if (accumBits > 0) {
> +      osmesa->accum_format = PIPE_FORMAT_R16G16B16A16_SNORM;
> +   }
> +   if (depthBits > 0 && stencilBits > 0) {
> +      osmesa->depth_stencil_format = PIPE_FORMAT_Z24_UNORM_S8_UINT;
> +   }
> +   else if (stencilBits > 0) {
> +      osmesa->depth_stencil_format = PIPE_FORMAT_S8_UINT;
> +   }
> +   else if (depthBits >= 24) {
> +      osmesa->depth_stencil_format = PIPE_FORMAT_Z24X8_UNORM;
> +   }
> +   else if (depthBits >= 16) {
> +      osmesa->depth_stencil_format = PIPE_FORMAT_Z16_UNORM;
> +   }
> +
> +   /*
> +    * Create the rendering context
> +    */
> +   attribs.profile = ST_PROFILE_DEFAULT;
> +   attribs.major = 2;
> +   attribs.minor = 1;
> +   attribs.flags = 0;  /* ST_CONTEXT_FLAG_x */
> +   attribs.options.force_glsl_extensions_warn = FALSE;
> +
> +   osmesa_init_st_visual(&attribs.visual,
> +                         PIPE_FORMAT_R8G8B8A8_UNORM,
> +                         osmesa->depth_stencil_format,
> +                         osmesa->accum_format);
> +
> +   osmesa->stctx = stapi->create_context(stapi, get_st_manager(),
> +                                         &attribs, &st_error, st_shared);
> +   if (!osmesa->stctx) {
> +      FREE(osmesa);
> +      return NULL;
> +   }
> +
> +   osmesa->stctx->st_manager_private = osmesa;
> +
> +   osmesa->format = format;
> +   osmesa->user_row_length = 0;
> +   osmesa->y_up = GL_TRUE;
> +
> +   return osmesa;
> +}
> +
> +
> +/**
> + * Destroy an Off-Screen Mesa rendering context.
> + *
> + * \param osmesa  the context to destroy
> + */
> +GLAPI void GLAPIENTRY
> +OSMesaDestroyContext(OSMesaContext osmesa)
> +{
> +   if (osmesa) {
> +      osmesa->stctx->destroy(osmesa->stctx);
> +      FREE(osmesa);
> +   }
> +}
> +
> +
> +/**
> + * 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*pixelSize.  Its address should be a multiple
> + * of 4 if using RGBA mode.
> + *
> + * By default, 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
> + *                GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5,
> GL_UNSIGNED_SHORT
> + *                or GL_FLOAT.
> + *         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 type, invalid size, etc.
> + */
> +GLAPI GLboolean GLAPIENTRY
> +OSMesaMakeCurrent(OSMesaContext osmesa, void *buffer, GLenum type,
> +                  GLsizei width, GLsizei height)
> +{
> +   struct st_api *stapi = get_st_api();
> +   struct osmesa_buffer *osbuffer;
> +   enum pipe_format color_format;
> +
> +   if (osmesa->format == OSMESA_RGB_565 && type != GL_UNSIGNED_SHORT_5_6_5)
> {
> +      return GL_FALSE;
> +   }
> +   if (width < 1 || height < 1) {
> +      return GL_FALSE;
> +   }
> +
> +   color_format = osmesa_choose_format(osmesa->format, type);
> +   if (color_format == PIPE_FORMAT_NONE) {
> +      fprintf(stderr, "OSMesaMakeCurrent(unsupported format/type)\n");
> +      return GL_FALSE;
> +   }
> +
> +   osbuffer = osmesa_create_buffer(color_format,
> +                                   osmesa->depth_stencil_format,
> +                                   osmesa->accum_format);
> +
> +   osbuffer->width = width;
> +   osbuffer->height = height;
> +   osbuffer->map = buffer;
> +
> +   if (osmesa->current_buffer) {
> +      /* free old buffer */
> +      osmesa_destroy_buffer(osmesa->current_buffer);
> +   }
> +
> +   osmesa->current_buffer = osbuffer;
> +   osmesa->type = type;
> +
> +   stapi->make_current(stapi, osmesa->stctx, osbuffer->stfb,
> osbuffer->stfb);
> +
> +   return GL_TRUE;
> +}
> +
> +
> +
> +GLAPI OSMesaContext GLAPIENTRY
> +OSMesaGetCurrentContext(void)
> +{
> +   struct st_api *stapi = get_st_api();
> +   struct st_context_iface *st = stapi->get_current(stapi);
> +   return st ? (OSMesaContext) st->st_manager_private : NULL;
> +}
> +
> +
> +
> +GLAPI void GLAPIENTRY
> +OSMesaPixelStore(GLint pname, GLint value)
> +{
> +   OSMesaContext osmesa = OSMesaGetCurrentContext();
> +
> +   switch (pname) {
> +   case OSMESA_ROW_LENGTH:
> +      osmesa->user_row_length = value;
> +      break;
> +   case OSMESA_Y_UP:
> +      osmesa->y_up = value ? GL_TRUE : GL_FALSE;
> +      break;
> +   default:
> +      fprintf(stderr, "Invalid pname in OSMesaPixelStore()\n");
> +      return;
> +   }
> +}
> +
> +
> +GLAPI void GLAPIENTRY
> +OSMesaGetIntegerv(GLint pname, GLint *value)
> +{
> +   OSMesaContext osmesa = OSMesaGetCurrentContext();
> +   struct osmesa_buffer *osbuffer = osmesa ? osmesa->current_buffer : NULL;
> +
> +   switch (pname) {
> +   case OSMESA_WIDTH:
> +      *value = osbuffer ? osbuffer->width : 0;
> +      return;
> +   case OSMESA_HEIGHT:
> +      *value = osbuffer ? osbuffer->height : 0;
> +      return;
> +   case OSMESA_FORMAT:
> +      *value = osmesa->format;
> +      return;
> +   case OSMESA_TYPE:
> +      /* current color buffer's data type */
> +      *value = osmesa->type;
> +      return;
> +   case OSMESA_ROW_LENGTH:
> +      *value = osmesa->user_row_length;
> +      return;
> +   case OSMESA_Y_UP:
> +      *value = osmesa->y_up;
> +      return;
> +   case OSMESA_MAX_WIDTH:
> +      /* fall-through */
> +   case OSMESA_MAX_HEIGHT:
> +      {
> +         struct pipe_screen *screen = get_st_manager()->screen;
> +         int maxLevels = screen->get_param(screen,
> +                                           PIPE_CAP_MAX_TEXTURE_2D_LEVELS);
> +         *value = 1 << (maxLevels - 1);
> +         *value = 8 * 1024;
> +      }
> +      return;
> +   default:
> +      fprintf(stderr, "Invalid pname in OSMesaGetIntegerv()\n");
> +      return;
> +   }
> +}
> +
> +
> +/**
> + * Return information about the depth buffer associated with an OSMesa
> context.
> + * Input:  c - the OSMesa context
> + * Output:  width, height - size of buffer in pixels
> + *          bytesPerValue - bytes per depth value (2 or 4)
> + *          buffer - pointer to depth buffer values
> + * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
> + */
> +GLAPI GLboolean GLAPIENTRY
> +OSMesaGetDepthBuffer(OSMesaContext c, GLint *width, GLint *height,
> +                     GLint *bytesPerValue, void **buffer)
> +{
> +   struct osmesa_buffer *osbuffer = c->current_buffer;
> +   struct pipe_context *pipe = c->stctx->pipe;
> +   struct pipe_resource *res =
> osbuffer->textures[ST_ATTACHMENT_DEPTH_STENCIL];
> +   struct pipe_transfer *transfer = NULL;
> +   struct pipe_box box;
> +
> +   /*
> +    * Note: we can't really implement this function with gallium as
> +    * we did for swrast.  We can't just map the resource and leave it
> +    * mapped (and there's no OSMesaUnmapDepthBuffer() function) so
> +    * we unmap the buffer here and return a 'stale' pointer.  This should
> +    * actually be OK in most cases where the caller of this function
> +    * immediately uses the pointer.
> +    */
> +
> +   u_box_2d(0, 0, res->width0, res->height0, &box);
> +
> +   *buffer = pipe->transfer_map(pipe, res, 0, PIPE_TRANSFER_READ, &box,
> +                                &transfer);
> +   if (!*buffer) {
> +      return GL_FALSE;
> +   }
> +
> +   *width = res->width0;
> +   *height = res->height0;
> +   *bytesPerValue = util_format_get_blocksize(res->format);
> +
> +   pipe->transfer_unmap(pipe, transfer);
> +
> +   return GL_TRUE;
> +}
> +
> +
> +/**
> + * Return the color buffer associated with an OSMesa context.
> + * Input:  c - the OSMesa context
> + * Output:  width, height - size of buffer in pixels
> + *          format - the pixel format (OSMESA_FORMAT)
> + *          buffer - pointer to color buffer values
> + * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
> + */
> +GLAPI GLboolean GLAPIENTRY
> +OSMesaGetColorBuffer(OSMesaContext osmesa, GLint *width,
> +                      GLint *height, GLint *format, void **buffer)
> +{
> +   struct osmesa_buffer *osbuffer = osmesa->current_buffer;
> +
> +   if (osbuffer) {
> +      *width = osbuffer->width;
> +      *height = osbuffer->height;
> +      *format = osmesa->format;
> +      *buffer = osbuffer->map;
> +      return GL_TRUE;
> +   }
> +   else {
> +      *width = 0;
> +      *height = 0;
> +      *format = 0;
> +      *buffer = 0;
> +      return GL_FALSE;
> +   }
> +}
> +
> +
> +struct name_function
> +{
> +   const char *Name;
> +   OSMESAproc Function;
> +};
> +
> +static struct name_function functions[] = {
> +   { "OSMesaCreateContext", (OSMESAproc) OSMesaCreateContext },
> +   { "OSMesaCreateContextExt", (OSMESAproc) OSMesaCreateContextExt },
> +   { "OSMesaDestroyContext", (OSMESAproc) OSMesaDestroyContext },
> +   { "OSMesaMakeCurrent", (OSMESAproc) OSMesaMakeCurrent },
> +   { "OSMesaGetCurrentContext", (OSMESAproc) OSMesaGetCurrentContext },
> +   { "OSMesaPixelsStore", (OSMESAproc) OSMesaPixelStore },
> +   { "OSMesaGetIntegerv", (OSMESAproc) OSMesaGetIntegerv },
> +   { "OSMesaGetDepthBuffer", (OSMESAproc) OSMesaGetDepthBuffer },
> +   { "OSMesaGetColorBuffer", (OSMESAproc) OSMesaGetColorBuffer },
> +   { "OSMesaGetProcAddress", (OSMESAproc) OSMesaGetProcAddress },
> +   { "OSMesaColorClamp", (OSMESAproc) OSMesaColorClamp },
> +   { NULL, NULL }
> +};
> +
> +
> +GLAPI OSMESAproc GLAPIENTRY
> +OSMesaGetProcAddress(const char *funcName)
> +{
> +   int i;
> +   for (i = 0; functions[i].Name; i++) {
> +      if (strcmp(functions[i].Name, funcName) == 0)
> +         return functions[i].Function;
> +   }
> +   return _glapi_get_proc_address(funcName);
> +}
> +
> +
> +GLAPI void GLAPIENTRY
> +OSMesaColorClamp(GLboolean enable)
> +{
> +   extern void GLAPIENTRY _mesa_ClampColor(GLenum target, GLenum clamp);
> +
> +   _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR_ARB,
> +                    enable ? GL_TRUE : GL_FIXED_ONLY_ARB);
> +}
> +
> +
> +
> +
> +#if 0000
> +/**
> + * When GLX_INDIRECT_RENDERING is defined, some symbols are missing in
> + * libglapi.a.  We need to define them here.
> + */
> +#ifdef GLX_INDIRECT_RENDERING
> +
> +#define GL_GLEXT_PROTOTYPES
> +#include "GL/gl.h"
> +#include "glapi/glapi.h"
> +#include "glapi/glapitable.h"
> +
> +#if defined(USE_MGL_NAMESPACE)
> +#define NAME(func)  mgl##func
> +#else
> +#define NAME(func)  gl##func
> +#endif
> +
> +#define DISPATCH(FUNC, ARGS, MESSAGE)        \
> +   GET_DISPATCH()->FUNC ARGS
> +
> +#define RETURN_DISPATCH(FUNC, ARGS, MESSAGE)     \
> +   return GET_DISPATCH()->FUNC ARGS
> +
> +/* skip normal ones */
> +#define _GLAPI_SKIP_NORMAL_ENTRY_POINTS
> +#include "glapi/glapitemp.h"
> +
> +#endif /* GLX_INDIRECT_RENDERING */
> +
> +#endif
> --
> 1.7.3.4
> 
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
> 


More information about the mesa-dev mailing list