Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright (c) 2013  Brian Paul   All Rights Reserved.
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the "Software"),
  6.  * to deal in the Software without restriction, including without limitation
  7.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8.  * and/or sell copies of the Software, and to permit persons to whom the
  9.  * Software is furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice shall be included
  12.  * in all copies or substantial portions of the Software.
  13.  *
  14.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  15.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20.  * OTHER DEALINGS IN THE SOFTWARE.
  21.  */
  22.  
  23.  
  24. /*
  25.  * Off-Screen rendering into client memory.
  26.  * State tracker for gallium (for softpipe and llvmpipe)
  27.  *
  28.  * Notes:
  29.  *
  30.  * If Gallium is built with LLVM support we use the llvmpipe driver.
  31.  * Otherwise we use softpipe.  The GALLIUM_DRIVER environment variable
  32.  * may be set to "softpipe" or "llvmpipe" to override.
  33.  *
  34.  * With softpipe we could render directly into the user's buffer by using a
  35.  * display target resource.  However, softpipe doesn't suport "upside-down"
  36.  * rendering which would be needed for the OSMESA_Y_UP=TRUE case.
  37.  *
  38.  * With llvmpipe we could only render directly into the user's buffer when its
  39.  * width and height is a multiple of the tile size (64 pixels).
  40.  *
  41.  * Because of these constraints we always render into ordinary resources then
  42.  * copy the results to the user's buffer in the flush_front() function which
  43.  * is called when the app calls glFlush/Finish.
  44.  *
  45.  * In general, the OSMesa interface is pretty ugly and not a good match
  46.  * for Gallium.  But we're interested in doing the best we can to preserve
  47.  * application portability.  With a little work we could come up with a
  48.  * much nicer, new off-screen Gallium interface...
  49.  */
  50.  
  51.  
  52. #include <stdio.h>
  53. #include "GL/osmesa.h"
  54.  
  55. #include "glapi/glapi.h"  /* for OSMesaGetProcAddress below */
  56.  
  57. #include "pipe/p_context.h"
  58. #include "pipe/p_screen.h"
  59. #include "pipe/p_state.h"
  60.  
  61. #include "util/u_atomic.h"
  62. #include "util/u_box.h"
  63. #include "util/u_debug.h"
  64. #include "util/u_format.h"
  65. #include "util/u_memory.h"
  66.  
  67. #include "postprocess/filters.h"
  68. #include "postprocess/postprocess.h"
  69.  
  70. #include "state_tracker/st_api.h"
  71. #include "state_tracker/st_gl_api.h"
  72.  
  73.  
  74.  
  75. extern struct pipe_screen *
  76. osmesa_create_screen(void);
  77.  
  78.  
  79.  
  80. struct osmesa_buffer
  81. {
  82.    struct st_framebuffer_iface *stfb;
  83.    struct st_visual visual;
  84.    unsigned width, height;
  85.  
  86.    struct pipe_resource *textures[ST_ATTACHMENT_COUNT];
  87.  
  88.    void *map;
  89.  
  90.    struct osmesa_buffer *next;  /**< next in linked list */
  91. };
  92.  
  93.  
  94. struct osmesa_context
  95. {
  96.    struct st_context_iface *stctx;
  97.  
  98.    boolean ever_used;     /*< Has this context ever been current? */
  99.  
  100.    struct osmesa_buffer *current_buffer;
  101.  
  102.    enum pipe_format depth_stencil_format, accum_format;
  103.  
  104.    GLenum format;         /*< User-specified context format */
  105.    GLenum type;           /*< Buffer's data type */
  106.    GLint user_row_length; /*< user-specified number of pixels per row */
  107.    GLboolean y_up;        /*< TRUE  -> Y increases upward */
  108.                           /*< FALSE -> Y increases downward */
  109.  
  110.    /** Which postprocessing filters are enabled. */
  111.    unsigned pp_enabled[PP_FILTERS];
  112.    struct pp_queue_t *pp;
  113. };
  114.  
  115.  
  116. /**
  117.  * Linked list of all osmesa_buffers.
  118.  * We can re-use an osmesa_buffer from one OSMesaMakeCurrent() call to
  119.  * the next unless the color/depth/stencil/accum formats change.
  120.  * We have to do this to be compatible with the original OSMesa implementation
  121.  * because some apps call OSMesaMakeCurrent() several times during rendering
  122.  * a frame.
  123.  */
  124. static struct osmesa_buffer *BufferList = NULL;
  125.  
  126.  
  127. /**
  128.  * Called from the ST manager.
  129.  */
  130. static int
  131. osmesa_st_get_param(struct st_manager *smapi, enum st_manager_param param)
  132. {
  133.    /* no-op */
  134.    return 0;
  135. }
  136.  
  137.  
  138. /**
  139.  * Create/return singleton st_api object.
  140.  */
  141. static struct st_api *
  142. get_st_api(void)
  143. {
  144.    static struct st_api *stapi = NULL;
  145.    if (!stapi) {
  146.       stapi = st_gl_api_create();
  147.    }
  148.    return stapi;
  149. }
  150.  
  151.  
  152. /**
  153.  * Create/return a singleton st_manager object.
  154.  */
  155. static struct st_manager *
  156. get_st_manager(void)
  157. {
  158.    static struct st_manager *stmgr = NULL;
  159.    if (!stmgr) {
  160.       stmgr = CALLOC_STRUCT(st_manager);
  161.       if (stmgr) {
  162.          stmgr->screen = osmesa_create_screen();
  163.          stmgr->get_param = osmesa_st_get_param;
  164.          stmgr->get_egl_image = NULL;
  165.       }        
  166.    }
  167.    return stmgr;
  168. }
  169.  
  170.  
  171. static INLINE boolean
  172. little_endian(void)
  173. {
  174.    const unsigned ui = 1;
  175.    return *((const char *) &ui);
  176. }
  177.  
  178.  
  179. /**
  180.  * Given an OSMESA_x format and a GL_y type, return the best
  181.  * matching PIPE_FORMAT_z.
  182.  * Note that we can't exactly match all user format/type combinations
  183.  * with gallium formats.  If we find this to be a problem, we can
  184.  * implement more elaborate format/type conversion in the flush_front()
  185.  * function.
  186.  */
  187. static enum pipe_format
  188. osmesa_choose_format(GLenum format, GLenum type)
  189. {
  190.    switch (format) {
  191.    case OSMESA_RGBA:
  192.       if (type == GL_UNSIGNED_BYTE) {
  193.          if (little_endian())
  194.             return PIPE_FORMAT_R8G8B8A8_UNORM;
  195.          else
  196.             return PIPE_FORMAT_A8B8G8R8_UNORM;
  197.       }
  198.       else if (type == GL_UNSIGNED_SHORT) {
  199.          return PIPE_FORMAT_R16G16B16A16_UNORM;
  200.       }
  201.       else if (type == GL_FLOAT) {
  202.          return PIPE_FORMAT_R32G32B32A32_FLOAT;
  203.       }
  204.       else {
  205.          return PIPE_FORMAT_NONE;
  206.       }
  207.       break;
  208.    case OSMESA_BGRA:
  209.       if (type == GL_UNSIGNED_BYTE) {
  210.          if (little_endian())
  211.             return PIPE_FORMAT_B8G8R8A8_UNORM;
  212.          else
  213.             return PIPE_FORMAT_A8R8G8B8_UNORM;
  214.       }
  215.       else if (type == GL_UNSIGNED_SHORT) {
  216.          return PIPE_FORMAT_R16G16B16A16_UNORM;
  217.       }
  218.       else if (type == GL_FLOAT) {
  219.          return PIPE_FORMAT_R32G32B32A32_FLOAT;
  220.       }
  221.       else {
  222.          return PIPE_FORMAT_NONE;
  223.       }
  224.       break;
  225.    case OSMESA_ARGB:
  226.       if (type == GL_UNSIGNED_BYTE) {
  227.          if (little_endian())
  228.             return PIPE_FORMAT_A8R8G8B8_UNORM;
  229.          else
  230.             return PIPE_FORMAT_B8G8R8A8_UNORM;
  231.       }
  232.       else if (type == GL_UNSIGNED_SHORT) {
  233.          return PIPE_FORMAT_R16G16B16A16_UNORM;
  234.       }
  235.       else if (type == GL_FLOAT) {
  236.          return PIPE_FORMAT_R32G32B32A32_FLOAT;
  237.       }
  238.       else {
  239.          return PIPE_FORMAT_NONE;
  240.       }
  241.       break;
  242.    case OSMESA_RGB:
  243.       if (type == GL_UNSIGNED_BYTE) {
  244.          return PIPE_FORMAT_R8G8B8_UNORM;
  245.       }
  246.       else if (type == GL_UNSIGNED_SHORT) {
  247.          return PIPE_FORMAT_R16G16B16_UNORM;
  248.       }
  249.       else if (type == GL_FLOAT) {
  250.          return PIPE_FORMAT_R32G32B32_FLOAT;
  251.       }
  252.       else {
  253.          return PIPE_FORMAT_NONE;
  254.       }
  255.       break;
  256.    case OSMESA_BGR:
  257.       /* No gallium format for this one */
  258.       return PIPE_FORMAT_NONE;
  259.    case OSMESA_RGB_565:
  260.       return PIPE_FORMAT_B5G6R5_UNORM;
  261.    default:
  262.       ; /* fall-through */
  263.    }
  264.    return PIPE_FORMAT_NONE;
  265. }
  266.  
  267.  
  268. /**
  269.  * Initialize an st_visual object.
  270.  */
  271. static void
  272. osmesa_init_st_visual(struct st_visual *vis,
  273.                       enum pipe_format color_format,
  274.                       enum pipe_format ds_format,
  275.                       enum pipe_format accum_format)
  276. {
  277.    vis->buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK;
  278.  
  279.    if (ds_format != PIPE_FORMAT_NONE)
  280.       vis->buffer_mask |= ST_ATTACHMENT_DEPTH_STENCIL_MASK;
  281.    if (accum_format != PIPE_FORMAT_NONE)
  282.       vis->buffer_mask |= ST_ATTACHMENT_ACCUM;
  283.  
  284.    vis->color_format = color_format;
  285.    vis->depth_stencil_format = ds_format;
  286.    vis->accum_format = accum_format;
  287.    vis->samples = 1;
  288.    vis->render_buffer = ST_ATTACHMENT_FRONT_LEFT;
  289. }
  290.  
  291.  
  292. /**
  293.  * Return the osmesa_buffer that corresponds to an st_framebuffer_iface.
  294.  */
  295. static INLINE struct osmesa_buffer *
  296. stfbi_to_osbuffer(struct st_framebuffer_iface *stfbi)
  297. {
  298.    return (struct osmesa_buffer *) stfbi->st_manager_private;
  299. }
  300.  
  301.  
  302. /**
  303.  * Called via glFlush/glFinish.  This is where we copy the contents
  304.  * of the driver's color buffer into the user-specified buffer.
  305.  */
  306. static boolean
  307. osmesa_st_framebuffer_flush_front(struct st_context_iface *stctx,
  308.                                   struct st_framebuffer_iface *stfbi,
  309.                                   enum st_attachment_type statt)
  310. {
  311.    OSMesaContext osmesa = OSMesaGetCurrentContext();
  312.    struct osmesa_buffer *osbuffer = stfbi_to_osbuffer(stfbi);
  313.    struct pipe_context *pipe = stctx->pipe;
  314.    struct pipe_resource *res = osbuffer->textures[statt];
  315.    struct pipe_transfer *transfer = NULL;
  316.    struct pipe_box box;
  317.    void *map;
  318.    ubyte *src, *dst;
  319.    unsigned y, bytes, bpp;
  320.    int dst_stride;
  321.  
  322.    if (osmesa->pp) {
  323.       struct pipe_resource *zsbuf = NULL;
  324.       unsigned i;
  325.  
  326.       /* Find the z/stencil buffer if there is one */
  327.       for (i = 0; i < Elements(osbuffer->textures); i++) {
  328.          struct pipe_resource *res = osbuffer->textures[i];
  329.          if (res) {
  330.             const struct util_format_description *desc =
  331.                util_format_description(res->format);
  332.  
  333.             if (util_format_has_depth(desc)) {
  334.                zsbuf = res;
  335.                break;
  336.             }
  337.          }
  338.       }
  339.  
  340.       /* run the postprocess stage(s) */
  341.       pp_run(osmesa->pp, res, res, zsbuf);
  342.    }
  343.  
  344.    u_box_2d(0, 0, res->width0, res->height0, &box);
  345.  
  346.    map = pipe->transfer_map(pipe, res, 0, PIPE_TRANSFER_READ, &box,
  347.                             &transfer);
  348.  
  349.    /*
  350.     * Copy the color buffer from the resource to the user's buffer.
  351.     */
  352.    bpp = util_format_get_blocksize(osbuffer->visual.color_format);
  353.    src = map;
  354.    dst = osbuffer->map;
  355.    if (osmesa->user_row_length)
  356.       dst_stride = bpp * osmesa->user_row_length;
  357.    else
  358.       dst_stride = bpp * osbuffer->width;
  359.    bytes = bpp * res->width0;
  360.  
  361.    if (osmesa->y_up) {
  362.       /* need to flip image upside down */
  363.       dst = dst + (res->height0 - 1) * dst_stride;
  364.       dst_stride = -dst_stride;
  365.    }
  366.  
  367.    for (y = 0; y < res->height0; y++) {
  368.       memcpy(dst, src, bytes);
  369.       dst += dst_stride;
  370.       src += transfer->stride;
  371.    }
  372.  
  373.    pipe->transfer_unmap(pipe, transfer);
  374.  
  375.    return TRUE;
  376. }
  377.  
  378.  
  379. /**
  380.  * Called by the st manager to validate the framebuffer (allocate
  381.  * its resources).
  382.  */
  383. static boolean
  384. osmesa_st_framebuffer_validate(struct st_context_iface *stctx,
  385.                                struct st_framebuffer_iface *stfbi,
  386.                                const enum st_attachment_type *statts,
  387.                                unsigned count,
  388.                                struct pipe_resource **out)
  389. {
  390.    struct pipe_screen *screen = get_st_manager()->screen;
  391.    enum st_attachment_type i;
  392.    struct osmesa_buffer *osbuffer = stfbi_to_osbuffer(stfbi);
  393.    struct pipe_resource templat;
  394.  
  395.    memset(&templat, 0, sizeof(templat));
  396.    templat.target = PIPE_TEXTURE_RECT;
  397.    templat.format = 0; /* setup below */
  398.    templat.last_level = 0;
  399.    templat.width0 = osbuffer->width;
  400.    templat.height0 = osbuffer->height;
  401.    templat.depth0 = 1;
  402.    templat.array_size = 1;
  403.    templat.usage = PIPE_USAGE_DEFAULT;
  404.    templat.bind = 0; /* setup below */
  405.    templat.flags = 0;
  406.  
  407.    for (i = 0; i < count; i++) {
  408.       enum pipe_format format = PIPE_FORMAT_NONE;
  409.       unsigned bind = 0;
  410.  
  411.       /*
  412.        * At this time, we really only need to handle the front-left color
  413.        * attachment, since that's all we specified for the visual in
  414.        * osmesa_init_st_visual().
  415.        */
  416.       if (statts[i] == ST_ATTACHMENT_FRONT_LEFT) {
  417.          format = osbuffer->visual.color_format;
  418.          bind = PIPE_BIND_RENDER_TARGET;
  419.       }
  420.       else if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) {
  421.          format = osbuffer->visual.depth_stencil_format;
  422.          bind = PIPE_BIND_DEPTH_STENCIL;
  423.       }
  424.       else if (statts[i] == ST_ATTACHMENT_ACCUM) {
  425.          format = osbuffer->visual.accum_format;
  426.          bind = PIPE_BIND_RENDER_TARGET;
  427.       }
  428.       else {
  429.          debug_warning("Unexpected attachment type in "
  430.                        "osmesa_st_framebuffer_validate()");
  431.       }
  432.  
  433.       templat.format = format;
  434.       templat.bind = bind;
  435.       out[i] = osbuffer->textures[statts[i]] =
  436.          screen->resource_create(screen, &templat);
  437.    }
  438.  
  439.    return TRUE;
  440. }
  441.  
  442.  
  443. static struct st_framebuffer_iface *
  444. osmesa_create_st_framebuffer(void)
  445. {
  446.    struct st_framebuffer_iface *stfbi = CALLOC_STRUCT(st_framebuffer_iface);
  447.    if (stfbi) {
  448.       stfbi->flush_front = osmesa_st_framebuffer_flush_front;
  449.       stfbi->validate = osmesa_st_framebuffer_validate;
  450.       p_atomic_set(&stfbi->stamp, 1);
  451.    }
  452.    return stfbi;
  453. }
  454.  
  455.  
  456. /**
  457.  * Create new buffer and add to linked list.
  458.  */
  459. static struct osmesa_buffer *
  460. osmesa_create_buffer(enum pipe_format color_format,
  461.                      enum pipe_format ds_format,
  462.                      enum pipe_format accum_format)
  463. {
  464.    struct osmesa_buffer *osbuffer = CALLOC_STRUCT(osmesa_buffer);
  465.    if (osbuffer) {
  466.       osbuffer->stfb = osmesa_create_st_framebuffer();
  467.  
  468.       osbuffer->stfb->st_manager_private = osbuffer;
  469.       osbuffer->stfb->visual = &osbuffer->visual;
  470.  
  471.       osmesa_init_st_visual(&osbuffer->visual, color_format,
  472.                             ds_format, accum_format);
  473.  
  474.       /* insert into linked list */
  475.       osbuffer->next = BufferList;
  476.       BufferList = osbuffer;
  477.    }
  478.  
  479.    return osbuffer;
  480. }
  481.  
  482.  
  483. /**
  484.  * Search linked list for a buffer with matching pixel formats and size.
  485.  */
  486. static struct osmesa_buffer *
  487. osmesa_find_buffer(enum pipe_format color_format,
  488.                    enum pipe_format ds_format,
  489.                    enum pipe_format accum_format,
  490.                    GLsizei width, GLsizei height)
  491. {
  492.    struct osmesa_buffer *b;
  493.  
  494.    /* Check if we already have a suitable buffer for the given formats */
  495.    for (b = BufferList; b; b = b->next) {
  496.       if (b->visual.color_format == color_format &&
  497.           b->visual.depth_stencil_format == ds_format &&
  498.           b->visual.accum_format == accum_format &&
  499.           b->width == width &&
  500.           b->height == height) {
  501.          return b;
  502.       }
  503.    }
  504.    return NULL;
  505. }
  506.  
  507.  
  508. static void
  509. osmesa_destroy_buffer(struct osmesa_buffer *osbuffer)
  510. {
  511.    FREE(osbuffer->stfb);
  512.    FREE(osbuffer);
  513. }
  514.  
  515.  
  516.  
  517. /**********************************************************************/
  518. /*****                    Public Functions                        *****/
  519. /**********************************************************************/
  520.  
  521.  
  522. /**
  523.  * Create an Off-Screen Mesa rendering context.  The only attribute needed is
  524.  * an RGBA vs Color-Index mode flag.
  525.  *
  526.  * Input:  format - Must be GL_RGBA
  527.  *         sharelist - specifies another OSMesaContext with which to share
  528.  *                     display lists.  NULL indicates no sharing.
  529.  * Return:  an OSMesaContext or 0 if error
  530.  */
  531. GLAPI OSMesaContext GLAPIENTRY
  532. OSMesaCreateContext(GLenum format, OSMesaContext sharelist)
  533. {
  534.    return OSMesaCreateContextExt(format, 24, 8, 0, sharelist);
  535. }
  536.  
  537.  
  538. /**
  539.  * New in Mesa 3.5
  540.  *
  541.  * Create context and specify size of ancillary buffers.
  542.  */
  543. GLAPI OSMesaContext GLAPIENTRY
  544. OSMesaCreateContextExt(GLenum format, GLint depthBits, GLint stencilBits,
  545.                        GLint accumBits, OSMesaContext sharelist)
  546. {
  547.    OSMesaContext osmesa;
  548.    struct st_context_iface *st_shared;
  549.    enum st_context_error st_error = 0;
  550.    struct st_context_attribs attribs;
  551.    struct st_api *stapi = get_st_api();
  552.  
  553.    if (sharelist) {
  554.       st_shared = sharelist->stctx;
  555.    }
  556.    else {
  557.       st_shared = NULL;
  558.    }
  559.  
  560.    osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context);
  561.    if (!osmesa)
  562.       return NULL;
  563.  
  564.    /* Choose depth/stencil/accum buffer formats */
  565.    if (accumBits > 0) {
  566.       osmesa->accum_format = PIPE_FORMAT_R16G16B16A16_SNORM;
  567.    }
  568.    if (depthBits > 0 && stencilBits > 0) {
  569.       osmesa->depth_stencil_format = PIPE_FORMAT_Z24_UNORM_S8_UINT;
  570.    }
  571.    else if (stencilBits > 0) {
  572.       osmesa->depth_stencil_format = PIPE_FORMAT_S8_UINT;
  573.    }
  574.    else if (depthBits >= 24) {
  575.       osmesa->depth_stencil_format = PIPE_FORMAT_Z24X8_UNORM;
  576.    }
  577.    else if (depthBits >= 16) {
  578.       osmesa->depth_stencil_format = PIPE_FORMAT_Z16_UNORM;
  579.    }
  580.  
  581.    /*
  582.     * Create the rendering context
  583.     */
  584.    attribs.profile = ST_PROFILE_DEFAULT;
  585.    attribs.major = 2;
  586.    attribs.minor = 1;
  587.    attribs.flags = 0;  /* ST_CONTEXT_FLAG_x */
  588.    attribs.options.force_glsl_extensions_warn = FALSE;
  589.    attribs.options.disable_blend_func_extended = FALSE;
  590.    attribs.options.disable_glsl_line_continuations = FALSE;
  591.    attribs.options.disable_shader_bit_encoding = FALSE;
  592.    attribs.options.force_s3tc_enable = FALSE;
  593.    attribs.options.force_glsl_version = 0;
  594.  
  595.    osmesa_init_st_visual(&attribs.visual,
  596.                          PIPE_FORMAT_R8G8B8A8_UNORM,
  597.                          osmesa->depth_stencil_format,
  598.                          osmesa->accum_format);
  599.  
  600.    osmesa->stctx = stapi->create_context(stapi, get_st_manager(),
  601.                                          &attribs, &st_error, st_shared);
  602.    if (!osmesa->stctx) {
  603.       FREE(osmesa);
  604.       return NULL;
  605.    }
  606.  
  607.    osmesa->stctx->st_manager_private = osmesa;
  608.  
  609.    osmesa->format = format;
  610.    osmesa->user_row_length = 0;
  611.    osmesa->y_up = GL_TRUE;
  612.  
  613.    return osmesa;
  614. }
  615.  
  616.  
  617. /**
  618.  * Destroy an Off-Screen Mesa rendering context.
  619.  *
  620.  * \param osmesa  the context to destroy
  621.  */
  622. GLAPI void GLAPIENTRY
  623. OSMesaDestroyContext(OSMesaContext osmesa)
  624. {
  625.    if (osmesa) {
  626.       pp_free(osmesa->pp);
  627.       osmesa->stctx->destroy(osmesa->stctx);
  628.       FREE(osmesa);
  629.    }
  630. }
  631.  
  632.  
  633. /**
  634.  * Bind an OSMesaContext to an image buffer.  The image buffer is just a
  635.  * block of memory which the client provides.  Its size must be at least
  636.  * as large as width*height*pixelSize.  Its address should be a multiple
  637.  * of 4 if using RGBA mode.
  638.  *
  639.  * By default, image data is stored in the order of glDrawPixels: row-major
  640.  * order with the lower-left image pixel stored in the first array position
  641.  * (ie. bottom-to-top).
  642.  *
  643.  * If the context's viewport hasn't been initialized yet, it will now be
  644.  * initialized to (0,0,width,height).
  645.  *
  646.  * Input:  osmesa - the rendering context
  647.  *         buffer - the image buffer memory
  648.  *         type - data type for pixel components
  649.  *                GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT
  650.  *                or GL_FLOAT.
  651.  *         width, height - size of image buffer in pixels, at least 1
  652.  * Return:  GL_TRUE if success, GL_FALSE if error because of invalid osmesa,
  653.  *          invalid type, invalid size, etc.
  654.  */
  655. GLAPI GLboolean GLAPIENTRY
  656. OSMesaMakeCurrent(OSMesaContext osmesa, void *buffer, GLenum type,
  657.                   GLsizei width, GLsizei height)
  658. {
  659.    struct st_api *stapi = get_st_api();
  660.    struct osmesa_buffer *osbuffer;
  661.    enum pipe_format color_format;
  662.  
  663.    if (!osmesa || !buffer || width < 1 || height < 1) {
  664.       return GL_FALSE;
  665.    }
  666.  
  667.    if (osmesa->format == OSMESA_RGB_565 && type != GL_UNSIGNED_SHORT_5_6_5) {
  668.       return GL_FALSE;
  669.    }
  670.  
  671.    color_format = osmesa_choose_format(osmesa->format, type);
  672.    if (color_format == PIPE_FORMAT_NONE) {
  673.       fprintf(stderr, "OSMesaMakeCurrent(unsupported format/type)\n");
  674.       return GL_FALSE;
  675.    }
  676.  
  677.    /* See if we already have a buffer that uses these pixel formats */
  678.    osbuffer = osmesa_find_buffer(color_format,
  679.                                  osmesa->depth_stencil_format,
  680.                                  osmesa->accum_format, width, height);
  681.    if (!osbuffer) {
  682.       /* Existing buffer found, create new buffer */
  683.       osbuffer = osmesa_create_buffer(color_format,
  684.                                       osmesa->depth_stencil_format,
  685.                                       osmesa->accum_format);
  686.    }
  687.  
  688.    osbuffer->width = width;
  689.    osbuffer->height = height;
  690.    osbuffer->map = buffer;
  691.  
  692.    /* XXX unused for now */
  693.    (void) osmesa_destroy_buffer;
  694.  
  695.    osmesa->current_buffer = osbuffer;
  696.    osmesa->type = type;
  697.  
  698.    stapi->make_current(stapi, osmesa->stctx, osbuffer->stfb, osbuffer->stfb);
  699.  
  700.    if (!osmesa->ever_used) {
  701.       /* one-time init, just postprocessing for now */
  702.       boolean any_pp_enabled = FALSE;
  703.       unsigned i;
  704.  
  705.       for (i = 0; i < Elements(osmesa->pp_enabled); i++) {
  706.          if (osmesa->pp_enabled[i]) {
  707.             any_pp_enabled = TRUE;
  708.             break;
  709.          }
  710.       }
  711.  
  712.       if (any_pp_enabled) {
  713.          osmesa->pp = pp_init(osmesa->stctx->pipe,
  714.                               osmesa->pp_enabled,
  715.                               osmesa->stctx->cso_context);
  716.  
  717.          pp_init_fbos(osmesa->pp, width, height);
  718.       }
  719.  
  720.       osmesa->ever_used = TRUE;
  721.    }
  722.  
  723.    return GL_TRUE;
  724. }
  725.  
  726.  
  727.  
  728. GLAPI OSMesaContext GLAPIENTRY
  729. OSMesaGetCurrentContext(void)
  730. {
  731.    struct st_api *stapi = get_st_api();
  732.    struct st_context_iface *st = stapi->get_current(stapi);
  733.    return st ? (OSMesaContext) st->st_manager_private : NULL;
  734. }
  735.  
  736.  
  737.  
  738. GLAPI void GLAPIENTRY
  739. OSMesaPixelStore(GLint pname, GLint value)
  740. {
  741.    OSMesaContext osmesa = OSMesaGetCurrentContext();
  742.  
  743.    switch (pname) {
  744.    case OSMESA_ROW_LENGTH:
  745.       osmesa->user_row_length = value;
  746.       break;
  747.    case OSMESA_Y_UP:
  748.       osmesa->y_up = value ? GL_TRUE : GL_FALSE;
  749.       break;
  750.    default:
  751.       fprintf(stderr, "Invalid pname in OSMesaPixelStore()\n");
  752.       return;
  753.    }
  754. }
  755.  
  756.  
  757. GLAPI void GLAPIENTRY
  758. OSMesaGetIntegerv(GLint pname, GLint *value)
  759. {
  760.    OSMesaContext osmesa = OSMesaGetCurrentContext();
  761.    struct osmesa_buffer *osbuffer = osmesa ? osmesa->current_buffer : NULL;
  762.  
  763.    switch (pname) {
  764.    case OSMESA_WIDTH:
  765.       *value = osbuffer ? osbuffer->width : 0;
  766.       return;
  767.    case OSMESA_HEIGHT:
  768.       *value = osbuffer ? osbuffer->height : 0;
  769.       return;
  770.    case OSMESA_FORMAT:
  771.       *value = osmesa->format;
  772.       return;
  773.    case OSMESA_TYPE:
  774.       /* current color buffer's data type */
  775.       *value = osmesa->type;
  776.       return;
  777.    case OSMESA_ROW_LENGTH:
  778.       *value = osmesa->user_row_length;
  779.       return;
  780.    case OSMESA_Y_UP:
  781.       *value = osmesa->y_up;
  782.       return;
  783.    case OSMESA_MAX_WIDTH:
  784.       /* fall-through */
  785.    case OSMESA_MAX_HEIGHT:
  786.       {
  787.          struct pipe_screen *screen = get_st_manager()->screen;
  788.          int maxLevels = screen->get_param(screen,
  789.                                            PIPE_CAP_MAX_TEXTURE_2D_LEVELS);
  790.          *value = 1 << (maxLevels - 1);
  791.          *value = 8 * 1024;
  792.       }
  793.       return;
  794.    default:
  795.       fprintf(stderr, "Invalid pname in OSMesaGetIntegerv()\n");
  796.       return;
  797.    }
  798. }
  799.  
  800.  
  801. /**
  802.  * Return information about the depth buffer associated with an OSMesa context.
  803.  * Input:  c - the OSMesa context
  804.  * Output:  width, height - size of buffer in pixels
  805.  *          bytesPerValue - bytes per depth value (2 or 4)
  806.  *          buffer - pointer to depth buffer values
  807.  * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
  808.  */
  809. GLAPI GLboolean GLAPIENTRY
  810. OSMesaGetDepthBuffer(OSMesaContext c, GLint *width, GLint *height,
  811.                      GLint *bytesPerValue, void **buffer)
  812. {
  813.    struct osmesa_buffer *osbuffer = c->current_buffer;
  814.    struct pipe_context *pipe = c->stctx->pipe;
  815.    struct pipe_resource *res = osbuffer->textures[ST_ATTACHMENT_DEPTH_STENCIL];
  816.    struct pipe_transfer *transfer = NULL;
  817.    struct pipe_box box;
  818.  
  819.    /*
  820.     * Note: we can't really implement this function with gallium as
  821.     * we did for swrast.  We can't just map the resource and leave it
  822.     * mapped (and there's no OSMesaUnmapDepthBuffer() function) so
  823.     * we unmap the buffer here and return a 'stale' pointer.  This should
  824.     * actually be OK in most cases where the caller of this function
  825.     * immediately uses the pointer.
  826.     */
  827.  
  828.    u_box_2d(0, 0, res->width0, res->height0, &box);
  829.  
  830.    *buffer = pipe->transfer_map(pipe, res, 0, PIPE_TRANSFER_READ, &box,
  831.                                 &transfer);
  832.    if (!*buffer) {
  833.       return GL_FALSE;
  834.    }
  835.  
  836.    *width = res->width0;
  837.    *height = res->height0;
  838.    *bytesPerValue = util_format_get_blocksize(res->format);
  839.  
  840.    pipe->transfer_unmap(pipe, transfer);
  841.  
  842.    return GL_TRUE;
  843. }
  844.  
  845.  
  846. /**
  847.  * Return the color buffer associated with an OSMesa context.
  848.  * Input:  c - the OSMesa context
  849.  * Output:  width, height - size of buffer in pixels
  850.  *          format - the pixel format (OSMESA_FORMAT)
  851.  *          buffer - pointer to color buffer values
  852.  * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
  853.  */
  854. GLAPI GLboolean GLAPIENTRY
  855. OSMesaGetColorBuffer(OSMesaContext osmesa, GLint *width,
  856.                       GLint *height, GLint *format, void **buffer)
  857. {
  858.    struct osmesa_buffer *osbuffer = osmesa->current_buffer;
  859.  
  860.    if (osbuffer) {
  861.       *width = osbuffer->width;
  862.       *height = osbuffer->height;
  863.       *format = osmesa->format;
  864.       *buffer = osbuffer->map;
  865.       return GL_TRUE;
  866.    }
  867.    else {
  868.       *width = 0;
  869.       *height = 0;
  870.       *format = 0;
  871.       *buffer = 0;
  872.       return GL_FALSE;
  873.    }
  874. }
  875.  
  876.  
  877. struct name_function
  878. {
  879.    const char *Name;
  880.    OSMESAproc Function;
  881. };
  882.  
  883. static struct name_function functions[] = {
  884.    { "OSMesaCreateContext", (OSMESAproc) OSMesaCreateContext },
  885.    { "OSMesaCreateContextExt", (OSMESAproc) OSMesaCreateContextExt },
  886.    { "OSMesaDestroyContext", (OSMESAproc) OSMesaDestroyContext },
  887.    { "OSMesaMakeCurrent", (OSMESAproc) OSMesaMakeCurrent },
  888.    { "OSMesaGetCurrentContext", (OSMESAproc) OSMesaGetCurrentContext },
  889.    { "OSMesaPixelsStore", (OSMESAproc) OSMesaPixelStore },
  890.    { "OSMesaGetIntegerv", (OSMESAproc) OSMesaGetIntegerv },
  891.    { "OSMesaGetDepthBuffer", (OSMESAproc) OSMesaGetDepthBuffer },
  892.    { "OSMesaGetColorBuffer", (OSMESAproc) OSMesaGetColorBuffer },
  893.    { "OSMesaGetProcAddress", (OSMESAproc) OSMesaGetProcAddress },
  894.    { "OSMesaColorClamp", (OSMESAproc) OSMesaColorClamp },
  895.    { "OSMesaPostprocess", (OSMESAproc) OSMesaPostprocess },
  896.    { NULL, NULL }
  897. };
  898.  
  899.  
  900. GLAPI OSMESAproc GLAPIENTRY
  901. OSMesaGetProcAddress(const char *funcName)
  902. {
  903.    int i;
  904.    for (i = 0; functions[i].Name; i++) {
  905.       if (strcmp(functions[i].Name, funcName) == 0)
  906.          return functions[i].Function;
  907.    }
  908.    return _glapi_get_proc_address(funcName);
  909. }
  910.  
  911.  
  912. GLAPI void GLAPIENTRY
  913. OSMesaColorClamp(GLboolean enable)
  914. {
  915.    extern void GLAPIENTRY _mesa_ClampColor(GLenum target, GLenum clamp);
  916.  
  917.    _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR_ARB,
  918.                     enable ? GL_TRUE : GL_FIXED_ONLY_ARB);
  919. }
  920.  
  921.  
  922. GLAPI void GLAPIENTRY
  923. OSMesaPostprocess(OSMesaContext osmesa, const char *filter,
  924.                   unsigned enable_value)
  925. {
  926.    if (!osmesa->ever_used) {
  927.       /* We can only enable/disable postprocess filters before a context
  928.        * is made current for the first time.
  929.        */
  930.       unsigned i;
  931.  
  932.       for (i = 0; i < PP_FILTERS; i++) {
  933.          if (strcmp(pp_filters[i].name, filter) == 0) {
  934.             osmesa->pp_enabled[i] = enable_value;
  935.             return;
  936.          }
  937.       }
  938.       debug_warning("OSMesaPostprocess(unknown filter)\n");
  939.    }
  940.    else {
  941.       debug_warning("Calling OSMesaPostprocess() after OSMesaMakeCurrent()\n");
  942.    }
  943. }
  944.