[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