Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright © 2014 Intel Corporation
  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 (including the next
  12.  * paragraph) shall be included in all copies or substantial portions of the
  13.  * Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21.  * IN THE SOFTWARE.
  22.  */
  23.  
  24. #include "brw_meta_util.h"
  25. #include "main/fbobject.h"
  26.  
  27. /**
  28.  * Helper function for handling mirror image blits.
  29.  *
  30.  * If coord0 > coord1, swap them and invert the "mirror" boolean.
  31.  */
  32. static inline void
  33. fixup_mirroring(bool *mirror, float *coord0, float *coord1)
  34. {
  35.    if (*coord0 > *coord1) {
  36.       *mirror = !*mirror;
  37.       float tmp = *coord0;
  38.       *coord0 = *coord1;
  39.       *coord1 = tmp;
  40.    }
  41. }
  42.  
  43. /**
  44.  * Adjust {src,dst}_x{0,1} to account for clipping and scissoring of
  45.  * destination coordinates.
  46.  *
  47.  * Return true if there is still blitting to do, false if all pixels got
  48.  * rejected by the clip and/or scissor.
  49.  *
  50.  * For clarity, the nomenclature of this function assumes we are clipping and
  51.  * scissoring the X coordinate; the exact same logic applies for Y
  52.  * coordinates.
  53.  *
  54.  * Note: this function may also be used to account for clipping of source
  55.  * coordinates, by swapping the roles of src and dst.
  56.  */
  57. static inline bool
  58. clip_or_scissor(bool mirror,
  59.                 GLfloat *src_x0, GLfloat *src_x1,
  60.                 GLfloat *dst_x0, GLfloat *dst_x1,
  61.                 GLfloat fb_xmin, GLfloat fb_xmax)
  62. {
  63.    float scale = (float) (*src_x1 - *src_x0) / (*dst_x1 - *dst_x0);
  64.    /* If we are going to scissor everything away, stop. */
  65.    if (!(fb_xmin < fb_xmax &&
  66.          *dst_x0 < fb_xmax &&
  67.          fb_xmin < *dst_x1 &&
  68.          *dst_x0 < *dst_x1)) {
  69.       return false;
  70.    }
  71.  
  72.    /* Clip the destination rectangle, and keep track of how many pixels we
  73.     * clipped off of the left and right sides of it.
  74.     */
  75.    int pixels_clipped_left = 0;
  76.    int pixels_clipped_right = 0;
  77.    if (*dst_x0 < fb_xmin) {
  78.       pixels_clipped_left = fb_xmin - *dst_x0;
  79.       *dst_x0 = fb_xmin;
  80.    }
  81.    if (fb_xmax < *dst_x1) {
  82.       pixels_clipped_right = *dst_x1 - fb_xmax;
  83.       *dst_x1 = fb_xmax;
  84.    }
  85.  
  86.    /* If we are mirrored, then before applying pixels_clipped_{left,right} to
  87.     * the source coordinates, we need to flip them to account for the
  88.     * mirroring.
  89.     */
  90.    if (mirror) {
  91.       int tmp = pixels_clipped_left;
  92.       pixels_clipped_left = pixels_clipped_right;
  93.       pixels_clipped_right = tmp;
  94.    }
  95.  
  96.    /* Adjust the source rectangle to remove the pixels corresponding to those
  97.     * that were clipped/scissored out of the destination rectangle.
  98.     */
  99.    *src_x0 += pixels_clipped_left * scale;
  100.    *src_x1 -= pixels_clipped_right * scale;
  101.  
  102.    return true;
  103. }
  104.  
  105. bool
  106. brw_meta_mirror_clip_and_scissor(const struct gl_context *ctx,
  107.                                  const struct gl_framebuffer *read_fb,
  108.                                  const struct gl_framebuffer *draw_fb,
  109.                                  GLfloat *srcX0, GLfloat *srcY0,
  110.                                  GLfloat *srcX1, GLfloat *srcY1,
  111.                                  GLfloat *dstX0, GLfloat *dstY0,
  112.                                  GLfloat *dstX1, GLfloat *dstY1,
  113.                                  bool *mirror_x, bool *mirror_y)
  114. {
  115.    *mirror_x = false;
  116.    *mirror_y = false;
  117.  
  118.    /* Detect if the blit needs to be mirrored */
  119.    fixup_mirroring(mirror_x, srcX0, srcX1);
  120.    fixup_mirroring(mirror_x, dstX0, dstX1);
  121.    fixup_mirroring(mirror_y, srcY0, srcY1);
  122.    fixup_mirroring(mirror_y, dstY0, dstY1);
  123.  
  124.    /* If the destination rectangle needs to be clipped or scissored, do so. */
  125.    if (!(clip_or_scissor(*mirror_x, srcX0, srcX1, dstX0, dstX1,
  126.                          draw_fb->_Xmin, draw_fb->_Xmax) &&
  127.          clip_or_scissor(*mirror_y, srcY0, srcY1, dstY0, dstY1,
  128.                          draw_fb->_Ymin, draw_fb->_Ymax))) {
  129.       /* Everything got clipped/scissored away, so the blit was successful. */
  130.       return true;
  131.    }
  132.  
  133.    /* If the source rectangle needs to be clipped or scissored, do so. */
  134.    if (!(clip_or_scissor(*mirror_x, dstX0, dstX1, srcX0, srcX1,
  135.                          0, read_fb->Width) &&
  136.          clip_or_scissor(*mirror_y, dstY0, dstY1, srcY0, srcY1,
  137.                          0, read_fb->Height))) {
  138.       /* Everything got clipped/scissored away, so the blit was successful. */
  139.       return true;
  140.    }
  141.  
  142.    /* Account for the fact that in the system framebuffer, the origin is at
  143.     * the lower left.
  144.     */
  145.    if (_mesa_is_winsys_fbo(read_fb)) {
  146.       GLint tmp = read_fb->Height - *srcY0;
  147.       *srcY0 = read_fb->Height - *srcY1;
  148.       *srcY1 = tmp;
  149.       *mirror_y = !*mirror_y;
  150.    }
  151.    if (_mesa_is_winsys_fbo(draw_fb)) {
  152.       GLint tmp = draw_fb->Height - *dstY0;
  153.       *dstY0 = draw_fb->Height - *dstY1;
  154.       *dstY1 = tmp;
  155.       *mirror_y = !*mirror_y;
  156.    }
  157.  
  158.    return false;
  159. }
  160.