Subversion Repositories Kolibri OS

Rev

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

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sub license, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial portions
  16.  * of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21.  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
  22.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  **************************************************************************/
  27.  
  28.  /*
  29.   * Authors:
  30.   *   Brian Paul
  31.   */
  32.  
  33. #include "main/imports.h"
  34. #include "main/image.h"
  35. #include "main/macros.h"
  36.  
  37. #include "st_context.h"
  38. #include "st_texture.h"
  39. #include "st_cb_blit.h"
  40. #include "st_cb_fbo.h"
  41. #include "st_atom.h"
  42.  
  43. #include "util/u_format.h"
  44.  
  45.  
  46. static void
  47. st_BlitFramebuffer(struct gl_context *ctx,
  48.                    GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
  49.                    GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
  50.                    GLbitfield mask, GLenum filter)
  51. {
  52.    const GLbitfield depthStencil = (GL_DEPTH_BUFFER_BIT |
  53.                                     GL_STENCIL_BUFFER_BIT);
  54.    struct st_context *st = st_context(ctx);
  55.    const uint pFilter = ((filter == GL_NEAREST)
  56.                          ? PIPE_TEX_FILTER_NEAREST
  57.                          : PIPE_TEX_FILTER_LINEAR);
  58.    struct gl_framebuffer *readFB = ctx->ReadBuffer;
  59.    struct gl_framebuffer *drawFB = ctx->DrawBuffer;
  60.    struct {
  61.       GLint srcX0, srcY0, srcX1, srcY1;
  62.       GLint dstX0, dstY0, dstX1, dstY1;
  63.    } clip;
  64.    struct pipe_blit_info blit;
  65.  
  66.    st_validate_state(st);
  67.  
  68.    clip.srcX0 = srcX0;
  69.    clip.srcY0 = srcY0;
  70.    clip.srcX1 = srcX1;
  71.    clip.srcY1 = srcY1;
  72.    clip.dstX0 = dstX0;
  73.    clip.dstY0 = dstY0;
  74.    clip.dstX1 = dstX1;
  75.    clip.dstY1 = dstY1;
  76.  
  77.    /* NOTE: If the src and dst dimensions don't match, we cannot simply adjust
  78.     * the integer coordinates to account for clipping (or scissors) because that
  79.     * would make us cut off fractional parts, affecting the result of the blit.
  80.     *
  81.     * XXX: This should depend on mask !
  82.     */
  83.    if (!_mesa_clip_blit(ctx,
  84.                         &clip.srcX0, &clip.srcY0, &clip.srcX1, &clip.srcY1,
  85.                         &clip.dstX0, &clip.dstY0, &clip.dstX1, &clip.dstY1)) {
  86.       return; /* nothing to draw/blit */
  87.    }
  88.    blit.scissor_enable =
  89.       (dstX0 != clip.dstX0) ||
  90.       (dstY0 != clip.dstY0) ||
  91.       (dstX1 != clip.dstX1) ||
  92.       (dstY1 != clip.dstY1);
  93.  
  94.    if (st_fb_orientation(drawFB) == Y_0_TOP) {
  95.       /* invert Y for dest */
  96.       dstY0 = drawFB->Height - dstY0;
  97.       dstY1 = drawFB->Height - dstY1;
  98.       /* invert Y for clip */
  99.       clip.dstY0 = drawFB->Height - clip.dstY0;
  100.       clip.dstY1 = drawFB->Height - clip.dstY1;
  101.    }
  102.    if (blit.scissor_enable) {
  103.       blit.scissor.minx = MIN2(clip.dstX0, clip.dstX1);
  104.       blit.scissor.miny = MIN2(clip.dstY0, clip.dstY1);
  105.       blit.scissor.maxx = MAX2(clip.dstX0, clip.dstX1);
  106.       blit.scissor.maxy = MAX2(clip.dstY0, clip.dstY1);
  107. #if 0
  108.       debug_printf("scissor = (%i,%i)-(%i,%i)\n",
  109.                    blit.scissor.minx,blit.scissor.miny,
  110.                    blit.scissor.maxx,blit.scissor.maxy);
  111. #endif
  112.    }
  113.  
  114.    if (st_fb_orientation(readFB) == Y_0_TOP) {
  115.       /* invert Y for src */
  116.       srcY0 = readFB->Height - srcY0;
  117.       srcY1 = readFB->Height - srcY1;
  118.    }
  119.  
  120.    if (srcY0 > srcY1 && dstY0 > dstY1) {
  121.       /* Both src and dst are upside down.  Swap Y to make it
  122.        * right-side up to increase odds of using a fast path.
  123.        * Recall that all Gallium raster coords have Y=0=top.
  124.        */
  125.       GLint tmp;
  126.       tmp = srcY0;
  127.       srcY0 = srcY1;
  128.       srcY1 = tmp;
  129.       tmp = dstY0;
  130.       dstY0 = dstY1;
  131.       dstY1 = tmp;
  132.    }
  133.  
  134.    blit.src.box.depth = 1;
  135.    blit.dst.box.depth = 1;
  136.  
  137.    /* Destination dimensions have to be positive: */
  138.    if (dstX0 < dstX1) {
  139.       blit.dst.box.x = dstX0;
  140.       blit.src.box.x = srcX0;
  141.       blit.dst.box.width = dstX1 - dstX0;
  142.       blit.src.box.width = srcX1 - srcX0;
  143.    } else {
  144.       blit.dst.box.x = dstX1;
  145.       blit.src.box.x = srcX1;
  146.       blit.dst.box.width = dstX0 - dstX1;
  147.       blit.src.box.width = srcX0 - srcX1;
  148.    }
  149.    if (dstY0 < dstY1) {
  150.       blit.dst.box.y = dstY0;
  151.       blit.src.box.y = srcY0;
  152.       blit.dst.box.height = dstY1 - dstY0;
  153.       blit.src.box.height = srcY1 - srcY0;
  154.    } else {
  155.       blit.dst.box.y = dstY1;
  156.       blit.src.box.y = srcY1;
  157.       blit.dst.box.height = dstY0 - dstY1;
  158.       blit.src.box.height = srcY0 - srcY1;
  159.    }
  160.  
  161.    blit.filter = pFilter;
  162.  
  163.    if (mask & GL_COLOR_BUFFER_BIT) {
  164.       struct gl_renderbuffer_attachment *srcAtt =
  165.          &readFB->Attachment[readFB->_ColorReadBufferIndex];
  166.  
  167.       blit.mask = PIPE_MASK_RGBA;
  168.  
  169.       if (srcAtt->Type == GL_TEXTURE) {
  170.          struct st_texture_object *srcObj = st_texture_object(srcAtt->Texture);
  171.          GLuint i;
  172.  
  173.          if (!srcObj || !srcObj->pt) {
  174.             return;
  175.          }
  176.  
  177.          for (i = 0; i < drawFB->_NumColorDrawBuffers; i++) {
  178.             struct st_renderbuffer *dstRb =
  179.                st_renderbuffer(drawFB->_ColorDrawBuffers[i]);
  180.  
  181.             if (dstRb) {
  182.                struct pipe_surface *dstSurf = dstRb->surface;
  183.  
  184.                if (dstSurf) {
  185.                   blit.dst.resource = dstSurf->texture;
  186.                   blit.dst.level = dstSurf->u.tex.level;
  187.                   blit.dst.box.z = dstSurf->u.tex.first_layer;
  188.                   blit.dst.format = util_format_linear(dstSurf->format);
  189.  
  190.                   blit.src.resource = srcObj->pt;
  191.                   blit.src.level = srcAtt->TextureLevel;
  192.                   blit.src.box.z = srcAtt->Zoffset + srcAtt->CubeMapFace;
  193.                   blit.src.format = util_format_linear(srcObj->pt->format);
  194.  
  195.                   st->pipe->blit(st->pipe, &blit);
  196.                }
  197.             }
  198.          }
  199.       }
  200.       else {
  201.          struct st_renderbuffer *srcRb =
  202.             st_renderbuffer(readFB->_ColorReadBuffer);
  203.          struct pipe_surface *srcSurf;
  204.          GLuint i;
  205.  
  206.          if (!srcRb || !srcRb->surface) {
  207.             return;
  208.          }
  209.  
  210.          srcSurf = srcRb->surface;
  211.  
  212.          for (i = 0; i < drawFB->_NumColorDrawBuffers; i++) {
  213.             struct st_renderbuffer *dstRb =
  214.                st_renderbuffer(drawFB->_ColorDrawBuffers[i]);
  215.  
  216.             if (dstRb) {
  217.                struct pipe_surface *dstSurf = dstRb->surface;
  218.  
  219.                if (dstSurf) {
  220.                   blit.dst.resource = dstSurf->texture;
  221.                   blit.dst.level = dstSurf->u.tex.level;
  222.                   blit.dst.box.z = dstSurf->u.tex.first_layer;
  223.                   blit.dst.format = util_format_linear(dstSurf->format);
  224.  
  225.                   blit.src.resource = srcSurf->texture;
  226.                   blit.src.level = srcSurf->u.tex.level;
  227.                   blit.src.box.z = srcSurf->u.tex.first_layer;
  228.                   blit.src.format = util_format_linear(srcSurf->format);
  229.  
  230.                   st->pipe->blit(st->pipe, &blit);
  231.                }
  232.             }
  233.          }
  234.       }
  235.    }
  236.  
  237.    if (mask & depthStencil) {
  238.       /* depth and/or stencil blit */
  239.  
  240.       /* get src/dst depth surfaces */
  241.       struct st_renderbuffer *srcDepthRb =
  242.          st_renderbuffer(readFB->Attachment[BUFFER_DEPTH].Renderbuffer);
  243.       struct st_renderbuffer *dstDepthRb =
  244.          st_renderbuffer(drawFB->Attachment[BUFFER_DEPTH].Renderbuffer);
  245.       struct pipe_surface *dstDepthSurf =
  246.          dstDepthRb ? dstDepthRb->surface : NULL;
  247.  
  248.       struct st_renderbuffer *srcStencilRb =
  249.          st_renderbuffer(readFB->Attachment[BUFFER_STENCIL].Renderbuffer);
  250.       struct st_renderbuffer *dstStencilRb =
  251.          st_renderbuffer(drawFB->Attachment[BUFFER_STENCIL].Renderbuffer);
  252.       struct pipe_surface *dstStencilSurf =
  253.          dstStencilRb ? dstStencilRb->surface : NULL;
  254.  
  255.       if (_mesa_has_depthstencil_combined(readFB) &&
  256.           _mesa_has_depthstencil_combined(drawFB)) {
  257.          blit.mask = 0;
  258.          if (mask & GL_DEPTH_BUFFER_BIT)
  259.             blit.mask |= PIPE_MASK_Z;
  260.          if (mask & GL_STENCIL_BUFFER_BIT)
  261.             blit.mask |= PIPE_MASK_S;
  262.  
  263.          blit.dst.resource = dstDepthSurf->texture;
  264.          blit.dst.level = dstDepthSurf->u.tex.level;
  265.          blit.dst.box.z = dstDepthSurf->u.tex.first_layer;
  266.          blit.dst.format = dstDepthSurf->format;
  267.  
  268.          blit.src.resource = srcDepthRb->texture;
  269.          blit.src.level = srcDepthRb->surface->u.tex.level;
  270.          blit.src.box.z = srcDepthRb->surface->u.tex.first_layer;
  271.          blit.src.format = srcDepthRb->surface->format;
  272.  
  273.          st->pipe->blit(st->pipe, &blit);
  274.       }
  275.       else {
  276.          /* blitting depth and stencil separately */
  277.  
  278.          if (mask & GL_DEPTH_BUFFER_BIT) {
  279.             blit.mask = PIPE_MASK_Z;
  280.  
  281.             blit.dst.resource = dstDepthSurf->texture;
  282.             blit.dst.level = dstDepthSurf->u.tex.level;
  283.             blit.dst.box.z = dstDepthSurf->u.tex.first_layer;
  284.             blit.dst.format = dstDepthSurf->format;
  285.  
  286.             blit.src.resource = srcDepthRb->texture;
  287.             blit.src.level = srcDepthRb->surface->u.tex.level;
  288.             blit.src.box.z = srcDepthRb->surface->u.tex.first_layer;
  289.             blit.src.format = srcDepthRb->surface->format;
  290.  
  291.             st->pipe->blit(st->pipe, &blit);
  292.          }
  293.  
  294.          if (mask & GL_STENCIL_BUFFER_BIT) {
  295.             blit.mask = PIPE_MASK_S;
  296.  
  297.             blit.dst.resource = dstStencilSurf->texture;
  298.             blit.dst.level = dstStencilSurf->u.tex.level;
  299.             blit.dst.box.z = dstStencilSurf->u.tex.first_layer;
  300.             blit.dst.format = dstStencilSurf->format;
  301.  
  302.             blit.src.resource = srcStencilRb->texture;
  303.             blit.src.level = srcStencilRb->surface->u.tex.level;
  304.             blit.src.box.z = srcStencilRb->surface->u.tex.first_layer;
  305.             blit.src.format = srcStencilRb->surface->format;
  306.  
  307.             st->pipe->blit(st->pipe, &blit);
  308.          }
  309.       }
  310.    }
  311. }
  312.  
  313.  
  314. void
  315. st_init_blit_functions(struct dd_function_table *functions)
  316. {
  317.    functions->BlitFramebuffer = st_BlitFramebuffer;
  318. }
  319.