Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  * Version:  7.9
  4.  *
  5.  * Copyright (C) 2010 LunarG Inc.
  6.  *
  7.  * Permission is hereby granted, free of charge, to any person obtaining a
  8.  * copy of this software and associated documentation files (the "Software"),
  9.  * to deal in the Software without restriction, including without limitation
  10.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11.  * and/or sell copies of the Software, and to permit persons to whom the
  12.  * Software is furnished to do so, subject to the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice shall be included
  15.  * in all copies or substantial portions of the Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  20.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  23.  * DEALINGS IN THE SOFTWARE.
  24.  *
  25.  * Authors:
  26.  *    Chia-I Wu <olv@lunarg.com>
  27.  */
  28.  
  29. #include "state_tracker/st_gl_api.h"
  30.  
  31. #include "pipe/p_context.h"
  32. #include "pipe/p_screen.h"
  33. #include "util/u_format.h"
  34. #include "util/u_pointer.h"
  35. #include "util/u_inlines.h"
  36. #include "util/u_atomic.h"
  37. #include "util/u_surface.h"
  38.  
  39. #include "main/mtypes.h"
  40. #include "main/context.h"
  41. #include "main/texobj.h"
  42. #include "main/teximage.h"
  43. #include "main/texstate.h"
  44. #include "main/framebuffer.h"
  45. #include "main/fbobject.h"
  46. #include "main/renderbuffer.h"
  47. #include "main/version.h"
  48. #include "st_texture.h"
  49.  
  50. #include "st_context.h"
  51. #include "st_format.h"
  52. #include "st_cb_fbo.h"
  53. #include "st_cb_flush.h"
  54. #include "st_manager.h"
  55.  
  56. /**
  57.  * Cast wrapper to convert a struct gl_framebuffer to an st_framebuffer.
  58.  * Return NULL if the struct gl_framebuffer is a user-created framebuffer.
  59.  * We'll only return non-null for window system framebuffers.
  60.  * Note that this function may fail.
  61.  */
  62. static INLINE struct st_framebuffer *
  63. st_ws_framebuffer(struct gl_framebuffer *fb)
  64. {
  65.    /* FBO cannot be casted.  See st_new_framebuffer */
  66.    return (struct st_framebuffer *) ((fb && !fb->Name) ? fb : NULL);
  67. }
  68.  
  69. /**
  70.  * Map an attachment to a buffer index.
  71.  */
  72. static INLINE gl_buffer_index
  73. attachment_to_buffer_index(enum st_attachment_type statt)
  74. {
  75.    gl_buffer_index index;
  76.  
  77.    switch (statt) {
  78.    case ST_ATTACHMENT_FRONT_LEFT:
  79.       index = BUFFER_FRONT_LEFT;
  80.       break;
  81.    case ST_ATTACHMENT_BACK_LEFT:
  82.       index = BUFFER_BACK_LEFT;
  83.       break;
  84.    case ST_ATTACHMENT_FRONT_RIGHT:
  85.       index = BUFFER_FRONT_RIGHT;
  86.       break;
  87.    case ST_ATTACHMENT_BACK_RIGHT:
  88.       index = BUFFER_BACK_RIGHT;
  89.       break;
  90.    case ST_ATTACHMENT_DEPTH_STENCIL:
  91.       index = BUFFER_DEPTH;
  92.       break;
  93.    case ST_ATTACHMENT_ACCUM:
  94.       index = BUFFER_ACCUM;
  95.       break;
  96.    case ST_ATTACHMENT_SAMPLE:
  97.    default:
  98.       index = BUFFER_COUNT;
  99.       break;
  100.    }
  101.  
  102.    return index;
  103. }
  104.  
  105. /**
  106.  * Map a buffer index to an attachment.
  107.  */
  108. static INLINE enum st_attachment_type
  109. buffer_index_to_attachment(gl_buffer_index index)
  110. {
  111.    enum st_attachment_type statt;
  112.  
  113.    switch (index) {
  114.    case BUFFER_FRONT_LEFT:
  115.       statt = ST_ATTACHMENT_FRONT_LEFT;
  116.       break;
  117.    case BUFFER_BACK_LEFT:
  118.       statt = ST_ATTACHMENT_BACK_LEFT;
  119.       break;
  120.    case BUFFER_FRONT_RIGHT:
  121.       statt = ST_ATTACHMENT_FRONT_RIGHT;
  122.       break;
  123.    case BUFFER_BACK_RIGHT:
  124.       statt = ST_ATTACHMENT_BACK_RIGHT;
  125.       break;
  126.    case BUFFER_DEPTH:
  127.       statt = ST_ATTACHMENT_DEPTH_STENCIL;
  128.       break;
  129.    case BUFFER_ACCUM:
  130.       statt = ST_ATTACHMENT_ACCUM;
  131.       break;
  132.    default:
  133.       statt = ST_ATTACHMENT_INVALID;
  134.       break;
  135.    }
  136.  
  137.    return statt;
  138. }
  139.  
  140. /**
  141.  * Validate a framebuffer to make sure up-to-date pipe_textures are used.
  142.  */
  143. static void
  144. st_framebuffer_validate(struct st_framebuffer *stfb, struct st_context *st)
  145. {
  146.    struct pipe_context *pipe = st->pipe;
  147.    struct pipe_resource *textures[ST_ATTACHMENT_COUNT];
  148.    uint width, height;
  149.    unsigned i;
  150.    boolean changed = FALSE;
  151.  
  152.    if (!p_atomic_read(&stfb->revalidate))
  153.       return;
  154.  
  155.    /* validate the fb */
  156.    if (!stfb->iface->validate(stfb->iface, stfb->statts, stfb->num_statts, textures))
  157.       return;
  158.  
  159.    width = stfb->Base.Width;
  160.    height = stfb->Base.Height;
  161.  
  162.    for (i = 0; i < stfb->num_statts; i++) {
  163.       struct st_renderbuffer *strb;
  164.       struct pipe_surface *ps, surf_tmpl;
  165.       gl_buffer_index idx;
  166.  
  167.       if (!textures[i])
  168.          continue;
  169.  
  170.       idx = attachment_to_buffer_index(stfb->statts[i]);
  171.       if (idx >= BUFFER_COUNT) {
  172.          pipe_resource_reference(&textures[i], NULL);
  173.          continue;
  174.       }
  175.  
  176.       strb = st_renderbuffer(stfb->Base.Attachment[idx].Renderbuffer);
  177.       assert(strb);
  178.       if (strb->texture == textures[i]) {
  179.          pipe_resource_reference(&textures[i], NULL);
  180.          continue;
  181.       }
  182.  
  183.       memset(&surf_tmpl, 0, sizeof(surf_tmpl));
  184.       u_surface_default_template(&surf_tmpl, textures[i],
  185.                                  PIPE_BIND_RENDER_TARGET);
  186.       ps = pipe->create_surface(pipe, textures[i], &surf_tmpl);
  187.       if (ps) {
  188.          pipe_surface_reference(&strb->surface, ps);
  189.          pipe_resource_reference(&strb->texture, ps->texture);
  190.          /* ownership transfered */
  191.          pipe_surface_reference(&ps, NULL);
  192.  
  193.          changed = TRUE;
  194.  
  195.          strb->Base.Width = strb->surface->width;
  196.          strb->Base.Height = strb->surface->height;
  197.  
  198.          width = strb->Base.Width;
  199.          height = strb->Base.Height;
  200.       }
  201.  
  202.       pipe_resource_reference(&textures[i], NULL);
  203.    }
  204.  
  205.    if (changed) {
  206.       st->dirty.st |= ST_NEW_FRAMEBUFFER;
  207.       _mesa_resize_framebuffer(st->ctx, &stfb->Base, width, height);
  208.  
  209.       assert(stfb->Base.Width == width);
  210.       assert(stfb->Base.Height == height);
  211.    }
  212.  
  213.    p_atomic_set(&stfb->revalidate, FALSE);
  214. }
  215.  
  216. /**
  217.  * Update the attachments to validate by looping the existing renderbuffers.
  218.  */
  219. static void
  220. st_framebuffer_update_attachments(struct st_framebuffer *stfb)
  221. {
  222.    gl_buffer_index idx;
  223.  
  224.    stfb->num_statts = 0;
  225.    for (idx = 0; idx < BUFFER_COUNT; idx++) {
  226.       struct st_renderbuffer *strb;
  227.       enum st_attachment_type statt;
  228.  
  229.       strb = st_renderbuffer(stfb->Base.Attachment[idx].Renderbuffer);
  230.       if (!strb || strb->software)
  231.          continue;
  232.  
  233.       statt = buffer_index_to_attachment(idx);
  234.       if (statt != ST_ATTACHMENT_INVALID &&
  235.           st_visual_have_buffers(stfb->iface->visual, 1 << statt))
  236.          stfb->statts[stfb->num_statts++] = statt;
  237.    }
  238.  
  239.    p_atomic_set(&stfb->revalidate, TRUE);
  240. }
  241.  
  242. /**
  243.  * Add a renderbuffer to the framebuffer.
  244.  */
  245. static boolean
  246. st_framebuffer_add_renderbuffer(struct st_framebuffer *stfb,
  247.                                 gl_buffer_index idx)
  248. {
  249.    struct gl_renderbuffer *rb;
  250.    enum pipe_format format;
  251.    int samples;
  252.    boolean sw;
  253.  
  254.    if (!stfb->iface)
  255.       return FALSE;
  256.  
  257.    /* do not distinguish depth/stencil buffers */
  258.    if (idx == BUFFER_STENCIL)
  259.       idx = BUFFER_DEPTH;
  260.  
  261.    switch (idx) {
  262.    case BUFFER_DEPTH:
  263.       format = stfb->iface->visual->depth_stencil_format;
  264.       sw = FALSE;
  265.       break;
  266.    case BUFFER_ACCUM:
  267.       format = stfb->iface->visual->accum_format;
  268.       sw = TRUE;
  269.       break;
  270.    default:
  271.       format = stfb->iface->visual->color_format;
  272.       sw = FALSE;
  273.       break;
  274.    }
  275.  
  276.    if (format == PIPE_FORMAT_NONE)
  277.       return FALSE;
  278.  
  279.    samples = stfb->iface->visual->samples;
  280.    if (!samples)
  281.       samples = st_get_msaa();
  282.  
  283.    rb = st_new_renderbuffer_fb(format, samples, sw);
  284.    if (!rb)
  285.       return FALSE;
  286.  
  287.    if (idx != BUFFER_DEPTH) {
  288.       _mesa_add_renderbuffer(&stfb->Base, idx, rb);
  289.    }
  290.    else {
  291.       if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 0))
  292.          _mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, rb);
  293.       if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 1))
  294.          _mesa_add_renderbuffer(&stfb->Base, BUFFER_STENCIL, rb);
  295.    }
  296.  
  297.    return TRUE;
  298. }
  299.  
  300. /**
  301.  * Intialize a struct gl_config from a visual.
  302.  */
  303. static void
  304. st_visual_to_context_mode(const struct st_visual *visual,
  305.                           struct gl_config *mode)
  306. {
  307.    memset(mode, 0, sizeof(*mode));
  308.  
  309.    if (st_visual_have_buffers(visual, ST_ATTACHMENT_BACK_LEFT_MASK))
  310.       mode->doubleBufferMode = GL_TRUE;
  311.    if (st_visual_have_buffers(visual,
  312.             ST_ATTACHMENT_FRONT_RIGHT_MASK | ST_ATTACHMENT_BACK_RIGHT_MASK))
  313.       mode->stereoMode = GL_TRUE;
  314.  
  315.    if (visual->color_format != PIPE_FORMAT_NONE) {
  316.       mode->rgbMode = GL_TRUE;
  317.  
  318.       mode->redBits =
  319.          util_format_get_component_bits(visual->color_format,
  320.                UTIL_FORMAT_COLORSPACE_RGB, 0);
  321.       mode->greenBits =
  322.          util_format_get_component_bits(visual->color_format,
  323.                UTIL_FORMAT_COLORSPACE_RGB, 1);
  324.       mode->blueBits =
  325.          util_format_get_component_bits(visual->color_format,
  326.                UTIL_FORMAT_COLORSPACE_RGB, 2);
  327.       mode->alphaBits =
  328.          util_format_get_component_bits(visual->color_format,
  329.                UTIL_FORMAT_COLORSPACE_RGB, 3);
  330.  
  331.       mode->rgbBits = mode->redBits +
  332.          mode->greenBits + mode->blueBits + mode->alphaBits;
  333.    }
  334.  
  335.    if (visual->depth_stencil_format != PIPE_FORMAT_NONE) {
  336.       mode->depthBits =
  337.          util_format_get_component_bits(visual->depth_stencil_format,
  338.                UTIL_FORMAT_COLORSPACE_ZS, 0);
  339.       mode->stencilBits =
  340.          util_format_get_component_bits(visual->depth_stencil_format,
  341.                UTIL_FORMAT_COLORSPACE_ZS, 1);
  342.  
  343.       mode->haveDepthBuffer = mode->depthBits > 0;
  344.       mode->haveStencilBuffer = mode->stencilBits > 0;
  345.    }
  346.  
  347.    if (visual->accum_format != PIPE_FORMAT_NONE) {
  348.       mode->haveAccumBuffer = GL_TRUE;
  349.  
  350.       mode->accumRedBits =
  351.          util_format_get_component_bits(visual->accum_format,
  352.                UTIL_FORMAT_COLORSPACE_RGB, 0);
  353.       mode->accumGreenBits =
  354.          util_format_get_component_bits(visual->accum_format,
  355.                UTIL_FORMAT_COLORSPACE_RGB, 1);
  356.       mode->accumBlueBits =
  357.          util_format_get_component_bits(visual->accum_format,
  358.                UTIL_FORMAT_COLORSPACE_RGB, 2);
  359.       mode->accumAlphaBits =
  360.          util_format_get_component_bits(visual->accum_format,
  361.                UTIL_FORMAT_COLORSPACE_RGB, 3);
  362.    }
  363.  
  364.    if (visual->samples) {
  365.       mode->sampleBuffers = 1;
  366.       mode->samples = visual->samples;
  367.    }
  368. }
  369.  
  370. /**
  371.  * Determine the default draw or read buffer from a visual.
  372.  */
  373. static void
  374. st_visual_to_default_buffer(const struct st_visual *visual,
  375.                             GLenum *buffer, GLint *index)
  376. {
  377.    enum st_attachment_type statt;
  378.    GLenum buf;
  379.    gl_buffer_index idx;
  380.  
  381.    statt = visual->render_buffer;
  382.    /* do nothing if an invalid render buffer is specified */
  383.    if (statt == ST_ATTACHMENT_INVALID ||
  384.        !st_visual_have_buffers(visual, 1 << statt))
  385.       return;
  386.  
  387.    switch (statt) {
  388.    case ST_ATTACHMENT_FRONT_LEFT:
  389.       buf = GL_FRONT_LEFT;
  390.       idx = BUFFER_FRONT_LEFT;
  391.       break;
  392.    case ST_ATTACHMENT_BACK_LEFT:
  393.       buf = GL_BACK_LEFT;
  394.       idx = BUFFER_BACK_LEFT;
  395.       break;
  396.    case ST_ATTACHMENT_FRONT_RIGHT:
  397.       buf = GL_FRONT_RIGHT;
  398.       idx = BUFFER_FRONT_RIGHT;
  399.       break;
  400.    case ST_ATTACHMENT_BACK_RIGHT:
  401.       buf = GL_BACK_RIGHT;
  402.       idx = BUFFER_BACK_RIGHT;
  403.       break;
  404.    default:
  405.       buf = GL_NONE;
  406.       idx = BUFFER_COUNT;
  407.       break;
  408.    }
  409.  
  410.    if (buf != GL_NONE) {
  411.       if (buffer)
  412.          *buffer = buf;
  413.       if (index)
  414.          *index = idx;
  415.    }
  416. }
  417.  
  418. /**
  419.  * Create a framebuffer from a manager interface.
  420.  */
  421. static struct st_framebuffer *
  422. st_framebuffer_create(struct st_framebuffer_iface *stfbi)
  423. {
  424.    struct st_framebuffer *stfb;
  425.    struct gl_config mode;
  426.    gl_buffer_index idx;
  427.  
  428.    stfb = CALLOC_STRUCT(st_framebuffer);
  429.    if (!stfb)
  430.       return NULL;
  431.  
  432.    /* for FBO-only context */
  433.    if (!stfbi) {
  434.       struct gl_framebuffer *base = _mesa_get_incomplete_framebuffer();
  435.  
  436.       stfb->Base = *base;
  437.  
  438.       return stfb;
  439.    }
  440.  
  441.    st_visual_to_context_mode(stfbi->visual, &mode);
  442.    _mesa_initialize_window_framebuffer(&stfb->Base, &mode);
  443.  
  444.    /* modify the draw/read buffers of the fb */
  445.    st_visual_to_default_buffer(stfbi->visual, &stfb->Base.ColorDrawBuffer[0],
  446.          &stfb->Base._ColorDrawBufferIndexes[0]);
  447.    st_visual_to_default_buffer(stfbi->visual, &stfb->Base.ColorReadBuffer,
  448.          &stfb->Base._ColorReadBufferIndex);
  449.  
  450.    stfb->iface = stfbi;
  451.  
  452.    /* add the color buffer */
  453.    idx = stfb->Base._ColorDrawBufferIndexes[0];
  454.    if (!st_framebuffer_add_renderbuffer(stfb, idx)) {
  455.       FREE(stfb);
  456.       return NULL;
  457.    }
  458.  
  459.    st_framebuffer_add_renderbuffer(stfb, BUFFER_DEPTH);
  460.    st_framebuffer_add_renderbuffer(stfb, BUFFER_ACCUM);
  461.  
  462.    st_framebuffer_update_attachments(stfb);
  463.  
  464.    stfb->Base.Initialized = GL_TRUE;
  465.  
  466.    return stfb;
  467. }
  468.  
  469. /**
  470.  * Reference a framebuffer.
  471.  */
  472. static void
  473. st_framebuffer_reference(struct st_framebuffer **ptr,
  474.                          struct st_framebuffer *stfb)
  475. {
  476.    struct gl_framebuffer *fb = &stfb->Base;
  477.    _mesa_reference_framebuffer((struct gl_framebuffer **) ptr, fb);
  478. }
  479.  
  480. static void
  481. st_context_notify_invalid_framebuffer(struct st_context_iface *stctxi,
  482.                                       struct st_framebuffer_iface *stfbi)
  483. {
  484.    struct st_context *st = (struct st_context *) stctxi;
  485.    struct st_framebuffer *stfb;
  486.  
  487.    /* either draw or read winsys fb */
  488.    stfb = st_ws_framebuffer(st->ctx->WinSysDrawBuffer);
  489.    if (!stfb || stfb->iface != stfbi)
  490.       stfb = st_ws_framebuffer(st->ctx->WinSysReadBuffer);
  491.  
  492.    if (stfb && stfb->iface == stfbi) {
  493.       p_atomic_set(&stfb->revalidate, TRUE);
  494.    }
  495.    else {
  496.       /* This function is probably getting called when we've detected a
  497.        * change in a window's size but the currently bound context is
  498.        * not bound to that window.
  499.        * If the st_framebuffer_iface structure had a pointer to the
  500.        * corresponding st_framebuffer we'd be able to handle this.
  501.        */
  502.    }
  503. }
  504.  
  505. static void
  506. st_context_flush(struct st_context_iface *stctxi, unsigned flags,
  507.                  struct pipe_fence_handle **fence)
  508. {
  509.    struct st_context *st = (struct st_context *) stctxi;
  510.    st_flush(st, flags, fence);
  511.    if (flags & PIPE_FLUSH_RENDER_CACHE)
  512.       st_manager_flush_frontbuffer(st);
  513. }
  514.  
  515. static boolean
  516. st_context_teximage(struct st_context_iface *stctxi, enum st_texture_type target,
  517.                     int level, enum pipe_format internal_format,
  518.                     struct pipe_resource *tex, boolean mipmap)
  519. {
  520.    struct st_context *st = (struct st_context *) stctxi;
  521.    struct gl_context *ctx = st->ctx;
  522.    struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
  523.    struct gl_texture_object *texObj;
  524.    struct gl_texture_image *texImage;
  525.    struct st_texture_object *stObj;
  526.    struct st_texture_image *stImage;
  527.    GLenum internalFormat;
  528.    GLuint width, height, depth;
  529.  
  530.    switch (target) {
  531.    case ST_TEXTURE_1D:
  532.       target = GL_TEXTURE_1D;
  533.       break;
  534.    case ST_TEXTURE_2D:
  535.       target = GL_TEXTURE_2D;
  536.       break;
  537.    case ST_TEXTURE_3D:
  538.       target = GL_TEXTURE_3D;
  539.       break;
  540.    case ST_TEXTURE_RECT:
  541.       target = GL_TEXTURE_RECTANGLE_ARB;
  542.       break;
  543.    default:
  544.       return FALSE;
  545.       break;
  546.    }
  547.  
  548.    texObj = _mesa_select_tex_object(ctx, texUnit, target);
  549.    _mesa_lock_texture(ctx, texObj);
  550.  
  551.    stObj = st_texture_object(texObj);
  552.    /* switch to surface based */
  553.    if (!stObj->surface_based) {
  554.       _mesa_clear_texture_object(ctx, texObj);
  555.       stObj->surface_based = GL_TRUE;
  556.    }
  557.  
  558.    texImage = _mesa_get_tex_image(ctx, texObj, target, level);
  559.    stImage = st_texture_image(texImage);
  560.    if (tex) {
  561.       gl_format texFormat;
  562.  
  563.       /*
  564.        * XXX When internal_format and tex->format differ, st_finalize_texture
  565.        * needs to allocate a new texture with internal_format and copy the
  566.        * texture here into the new one.  It will result in surface_copy being
  567.        * called on surfaces whose formats differ.
  568.        *
  569.        * To avoid that, internal_format is (wrongly) ignored here.  A sane fix
  570.        * is to use a sampler view.
  571.        */
  572.       if (!st_sampler_compat_formats(tex->format, internal_format))
  573.          internal_format = tex->format;
  574.      
  575.       if (util_format_get_component_bits(internal_format,
  576.                UTIL_FORMAT_COLORSPACE_RGB, 3) > 0)
  577.          internalFormat = GL_RGBA;
  578.       else
  579.          internalFormat = GL_RGB;
  580.  
  581.       texFormat = st_ChooseTextureFormat(ctx, internalFormat,
  582.                                          GL_RGBA, GL_UNSIGNED_BYTE);
  583.  
  584.       _mesa_init_teximage_fields(ctx, target, texImage,
  585.                                  tex->width0, tex->height0, 1, 0,
  586.                                  internalFormat, texFormat);
  587.  
  588.       width = tex->width0;
  589.       height = tex->height0;
  590.       depth = tex->depth0;
  591.  
  592.       /* grow the image size until we hit level = 0 */
  593.       while (level > 0) {
  594.          if (width != 1)
  595.             width <<= 1;
  596.          if (height != 1)
  597.             height <<= 1;
  598.          if (depth != 1)
  599.             depth <<= 1;
  600.          level--;
  601.       }
  602.    }
  603.    else {
  604.       _mesa_clear_texture_image(ctx, texImage);
  605.       width = height = depth = 0;
  606.    }
  607.  
  608.    pipe_resource_reference(&stImage->pt, tex);
  609.    stObj->width0 = width;
  610.    stObj->height0 = height;
  611.    stObj->depth0 = depth;
  612.  
  613.    _mesa_dirty_texobj(ctx, texObj, GL_TRUE);
  614.    _mesa_unlock_texture(ctx, texObj);
  615.    
  616.    return TRUE;
  617. }
  618.  
  619. static void
  620. st_context_copy(struct st_context_iface *stctxi,
  621.                 struct st_context_iface *stsrci, unsigned mask)
  622. {
  623.    struct st_context *st = (struct st_context *) stctxi;
  624.    struct st_context *src = (struct st_context *) stsrci;
  625.  
  626.    _mesa_copy_context(src->ctx, st->ctx, mask);
  627. }
  628.  
  629. static boolean
  630. st_context_share(struct st_context_iface *stctxi,
  631.                  struct st_context_iface *stsrci)
  632. {
  633.    struct st_context *st = (struct st_context *) stctxi;
  634.    struct st_context *src = (struct st_context *) stsrci;
  635.  
  636.    return _mesa_share_state(st->ctx, src->ctx);
  637. }
  638.  
  639. static void
  640. st_context_destroy(struct st_context_iface *stctxi)
  641. {
  642.    struct st_context *st = (struct st_context *) stctxi;
  643.    st_destroy_context(st);
  644. }
  645.  
  646. static struct st_context_iface *
  647. st_api_create_context(struct st_api *stapi, struct st_manager *smapi,
  648.                       const struct st_context_attribs *attribs,
  649.                       struct st_context_iface *shared_stctxi)
  650. {
  651.    struct st_context *shared_ctx = (struct st_context *) shared_stctxi;
  652.    struct st_context *st;
  653.    struct pipe_context *pipe;
  654.    struct gl_config mode;
  655.    gl_api api;
  656.  
  657.    if (!(stapi->profile_mask & (1 << attribs->profile)))
  658.       return NULL;
  659.  
  660.    switch (attribs->profile) {
  661.    case ST_PROFILE_DEFAULT:
  662.       api = API_OPENGL;
  663.       break;
  664.    case ST_PROFILE_OPENGL_ES1:
  665.       api = API_OPENGLES;
  666.       break;
  667.    case ST_PROFILE_OPENGL_ES2:
  668.       api = API_OPENGLES2;
  669.       break;
  670.    case ST_PROFILE_OPENGL_CORE:
  671.    default:
  672.       return NULL;
  673.       break;
  674.    }
  675.  
  676.    pipe = smapi->screen->context_create(smapi->screen, NULL);
  677.    if (!pipe)
  678.       return NULL;
  679.  
  680.    st_visual_to_context_mode(&attribs->visual, &mode);
  681.    st = st_create_context(api, pipe, &mode, shared_ctx);
  682.    if (!st) {
  683.       pipe->destroy(pipe);
  684.       return NULL;
  685.    }
  686.  
  687.    /* need to perform version check */
  688.    if (attribs->major > 1 || attribs->minor > 0) {
  689.       _mesa_compute_version(st->ctx);
  690.  
  691.       if (st->ctx->VersionMajor < attribs->major ||
  692.           st->ctx->VersionMajor < attribs->minor) {
  693.          st_destroy_context(st);
  694.          return NULL;
  695.       }
  696.    }
  697.  
  698.    st->invalidate_on_gl_viewport =
  699.       smapi->get_param(smapi, ST_MANAGER_BROKEN_INVALIDATE);
  700.  
  701.    st->iface.destroy = st_context_destroy;
  702.    st->iface.notify_invalid_framebuffer =
  703.       st_context_notify_invalid_framebuffer;
  704.    st->iface.flush = st_context_flush;
  705.    st->iface.teximage = st_context_teximage;
  706.    st->iface.copy = st_context_copy;
  707.    st->iface.share = st_context_share;
  708.    st->iface.st_context_private = (void *) smapi;
  709.  
  710.    return &st->iface;
  711. }
  712.  
  713. static boolean
  714. st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi,
  715.                     struct st_framebuffer_iface *stdrawi,
  716.                     struct st_framebuffer_iface *streadi)
  717. {
  718.    struct st_context *st = (struct st_context *) stctxi;
  719.    struct st_framebuffer *stdraw, *stread, *stfb;
  720.    boolean ret;
  721.  
  722.    _glapi_check_multithread();
  723.  
  724.    if (st) {
  725.       /* reuse/create the draw fb */
  726.       stfb = st_ws_framebuffer(st->ctx->WinSysDrawBuffer);
  727.       if (stfb && stfb->iface == stdrawi) {
  728.          stdraw = NULL;
  729.          st_framebuffer_reference(&stdraw, stfb);
  730.       }
  731.       else {
  732.          stdraw = st_framebuffer_create(stdrawi);
  733.       }
  734.  
  735.       /* reuse/create the read fb */
  736.       stfb = st_ws_framebuffer(st->ctx->WinSysReadBuffer);
  737.       if (!stfb || stfb->iface != streadi)
  738.          stfb = stdraw;
  739.       if (stfb && stfb->iface == streadi) {
  740.          stread = NULL;
  741.          st_framebuffer_reference(&stread, stfb);
  742.       }
  743.       else {
  744.          stread = st_framebuffer_create(streadi);
  745.       }
  746.  
  747.       if (stdraw && stread) {
  748.          st_framebuffer_validate(stdraw, st);
  749.          if (stread != stdraw)
  750.             st_framebuffer_validate(stread, st);
  751.  
  752.          /* modify the draw/read buffers of the context */
  753.          if (stdraw->iface) {
  754.             st_visual_to_default_buffer(stdraw->iface->visual,
  755.                   &st->ctx->Color.DrawBuffer[0], NULL);
  756.          }
  757.          if (stread->iface) {
  758.             st_visual_to_default_buffer(stread->iface->visual,
  759.                   &st->ctx->Pixel.ReadBuffer, NULL);
  760.          }
  761.  
  762.          ret = _mesa_make_current(st->ctx, &stdraw->Base, &stread->Base);
  763.       }
  764.       else {
  765.          ret = FALSE;
  766.       }
  767.  
  768.       st_framebuffer_reference(&stdraw, NULL);
  769.       st_framebuffer_reference(&stread, NULL);
  770.    }
  771.    else {
  772.       ret = _mesa_make_current(NULL, NULL, NULL);
  773.    }
  774.  
  775.    return ret;
  776. }
  777.  
  778. static struct st_context_iface *
  779. st_api_get_current(struct st_api *stapi)
  780. {
  781.    GET_CURRENT_CONTEXT(ctx);
  782.    struct st_context *st = (ctx) ? ctx->st : NULL;
  783.  
  784.    return (st) ? &st->iface : NULL;
  785. }
  786.  
  787. static st_proc_t
  788. st_api_get_proc_address(struct st_api *stapi, const char *procname)
  789. {
  790.    return (st_proc_t) _glapi_get_proc_address(procname);
  791. }
  792.  
  793. static void
  794. st_api_destroy(struct st_api *stapi)
  795. {
  796. }
  797.  
  798. /**
  799.  * Flush the front buffer if the current context renders to the front buffer.
  800.  */
  801. void
  802. st_manager_flush_frontbuffer(struct st_context *st)
  803. {
  804.    struct st_framebuffer *stfb = st_ws_framebuffer(st->ctx->DrawBuffer);
  805.    struct st_renderbuffer *strb = NULL;
  806.  
  807.    if (stfb)
  808.       strb = st_renderbuffer(stfb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
  809.    if (!strb)
  810.       return;
  811.  
  812.    /* never a dummy fb */
  813.    assert(stfb->iface);
  814.    stfb->iface->flush_front(stfb->iface, ST_ATTACHMENT_FRONT_LEFT);
  815. }
  816.  
  817. /**
  818.  * Return the surface of an EGLImage.
  819.  * FIXME: I think this should operate on resources, not surfaces
  820.  */
  821. struct pipe_surface *
  822. st_manager_get_egl_image_surface(struct st_context *st,
  823.                                  void *eglimg, unsigned usage)
  824. {
  825.    struct st_manager *smapi =
  826.       (struct st_manager *) st->iface.st_context_private;
  827.    struct st_egl_image stimg;
  828.    struct pipe_surface *ps, surf_tmpl;
  829.  
  830.    if (!smapi || !smapi->get_egl_image)
  831.       return NULL;
  832.  
  833.    memset(&stimg, 0, sizeof(stimg));
  834.    if (!smapi->get_egl_image(smapi, eglimg, &stimg))
  835.       return NULL;
  836.  
  837.    memset(&surf_tmpl, 0, sizeof(surf_tmpl));
  838.    surf_tmpl.format = stimg.texture->format;
  839.    surf_tmpl.usage = usage;
  840.    surf_tmpl.u.tex.level = stimg.level;
  841.    surf_tmpl.u.tex.first_layer = stimg.layer;
  842.    surf_tmpl.u.tex.last_layer = stimg.layer;
  843.    ps = st->pipe->create_surface(st->pipe, stimg.texture, &surf_tmpl);
  844.    pipe_resource_reference(&stimg.texture, NULL);
  845.  
  846.    return ps;
  847. }
  848.  
  849. /**
  850.  * Re-validate the framebuffers.
  851.  */
  852. void
  853. st_manager_validate_framebuffers(struct st_context *st)
  854. {
  855.    struct st_framebuffer *stdraw = st_ws_framebuffer(st->ctx->DrawBuffer);
  856.    struct st_framebuffer *stread = st_ws_framebuffer(st->ctx->ReadBuffer);
  857.  
  858.    if (stdraw)
  859.       st_framebuffer_validate(stdraw, st);
  860.    if (stread && stread != stdraw)
  861.       st_framebuffer_validate(stread, st);
  862. }
  863.  
  864. /**
  865.  * Add a color renderbuffer on demand.
  866.  */
  867. boolean
  868. st_manager_add_color_renderbuffer(struct st_context *st, struct gl_framebuffer *fb,
  869.                                   gl_buffer_index idx)
  870. {
  871.    struct st_framebuffer *stfb = st_ws_framebuffer(fb);
  872.  
  873.    /* FBO */
  874.    if (!stfb)
  875.       return FALSE;
  876.  
  877.    if (stfb->Base.Attachment[idx].Renderbuffer)
  878.       return TRUE;
  879.  
  880.    switch (idx) {
  881.    case BUFFER_FRONT_LEFT:
  882.    case BUFFER_BACK_LEFT:
  883.    case BUFFER_FRONT_RIGHT:
  884.    case BUFFER_BACK_RIGHT:
  885.       break;
  886.    default:
  887.       return FALSE;
  888.       break;
  889.    }
  890.  
  891.    if (!st_framebuffer_add_renderbuffer(stfb, idx))
  892.       return FALSE;
  893.  
  894.    st_framebuffer_update_attachments(stfb);
  895.    st_invalidate_state(st->ctx, _NEW_BUFFERS);
  896.  
  897.    return TRUE;
  898. }
  899.  
  900. static const struct st_api st_gl_api = {
  901.    "Mesa " MESA_VERSION_STRING,
  902.    ST_API_OPENGL,
  903. #if FEATURE_GL
  904.    ST_PROFILE_DEFAULT_MASK |
  905. #endif
  906. #if FEATURE_ES1
  907.    ST_PROFILE_OPENGL_ES1_MASK |
  908. #endif
  909. #if FEATURE_ES2
  910.    ST_PROFILE_OPENGL_ES2_MASK |
  911. #endif
  912.    0,
  913.    st_api_destroy,
  914.    st_api_get_proc_address,
  915.    st_api_create_context,
  916.    st_api_make_current,
  917.    st_api_get_current,
  918. };
  919.  
  920. struct st_api *
  921. st_gl_api_create(void)
  922. {
  923.    return (struct st_api *) &st_gl_api;
  924. }
  925.