Home | History | Annotate | Download | only in state_tracker
      1 /**************************************************************************
      2  *
      3  * Copyright 2007 VMware, Inc.
      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 VMWARE 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   *   Keith Whitwell <keithw (at) vmware.com>
     31   */
     32 
     33 
     34 #include "main/macros.h"
     35 #include "main/framebuffer.h"
     36 #include "st_context.h"
     37 #include "pipe/p_context.h"
     38 #include "st_atom.h"
     39 
     40 
     41 /**
     42  * Scissor depends on the scissor box, and the framebuffer dimensions.
     43  */
     44 static void
     45 update_scissor( struct st_context *st )
     46 {
     47    struct pipe_scissor_state scissor[PIPE_MAX_VIEWPORTS];
     48    const struct gl_context *ctx = st->ctx;
     49    const struct gl_framebuffer *fb = ctx->DrawBuffer;
     50    const unsigned int fb_width = _mesa_geometric_width(fb);
     51    const unsigned int fb_height = _mesa_geometric_height(fb);
     52    GLint miny, maxy;
     53    unsigned i;
     54    bool changed = false;
     55 
     56    for (i = 0 ; i < ctx->Const.MaxViewports; i++) {
     57       scissor[i].minx = 0;
     58       scissor[i].miny = 0;
     59       scissor[i].maxx = fb_width;
     60       scissor[i].maxy = fb_height;
     61 
     62       if (ctx->Scissor.EnableFlags & (1 << i)) {
     63          /* need to be careful here with xmax or ymax < 0 */
     64          GLint xmax = MAX2(0, ctx->Scissor.ScissorArray[i].X + ctx->Scissor.ScissorArray[i].Width);
     65          GLint ymax = MAX2(0, ctx->Scissor.ScissorArray[i].Y + ctx->Scissor.ScissorArray[i].Height);
     66 
     67          if (ctx->Scissor.ScissorArray[i].X > (GLint)scissor[i].minx)
     68             scissor[i].minx = ctx->Scissor.ScissorArray[i].X;
     69          if (ctx->Scissor.ScissorArray[i].Y > (GLint)scissor[i].miny)
     70             scissor[i].miny = ctx->Scissor.ScissorArray[i].Y;
     71 
     72          if (xmax < (GLint) scissor[i].maxx)
     73             scissor[i].maxx = xmax;
     74          if (ymax < (GLint) scissor[i].maxy)
     75             scissor[i].maxy = ymax;
     76 
     77          /* check for null space */
     78          if (scissor[i].minx >= scissor[i].maxx || scissor[i].miny >= scissor[i].maxy)
     79             scissor[i].minx = scissor[i].miny = scissor[i].maxx = scissor[i].maxy = 0;
     80       }
     81 
     82       /* Now invert Y if needed.
     83        * Gallium drivers use the convention Y=0=top for surfaces.
     84        */
     85       if (st_fb_orientation(fb) == Y_0_TOP) {
     86          miny = fb->Height - scissor[i].maxy;
     87          maxy = fb->Height - scissor[i].miny;
     88          scissor[i].miny = miny;
     89          scissor[i].maxy = maxy;
     90       }
     91 
     92       if (memcmp(&scissor[i], &st->state.scissor[i], sizeof(scissor[0])) != 0) {
     93          /* state has changed */
     94          st->state.scissor[i] = scissor[i];  /* struct copy */
     95          changed = true;
     96       }
     97    }
     98    if (changed)
     99       st->pipe->set_scissor_states(st->pipe, 0, ctx->Const.MaxViewports, scissor); /* activate */
    100 }
    101 
    102 static void
    103 update_window_rectangles(struct st_context *st)
    104 {
    105    struct pipe_scissor_state new_rects[PIPE_MAX_WINDOW_RECTANGLES];
    106    const struct gl_context *ctx = st->ctx;
    107    const struct gl_scissor_attrib *scissor = &ctx->Scissor;
    108    unsigned i;
    109    bool changed = false;
    110    unsigned num_rects = scissor->NumWindowRects;
    111    bool include = scissor->WindowRectMode == GL_INCLUSIVE_EXT;
    112 
    113    if (ctx->DrawBuffer == ctx->WinSysDrawBuffer) {
    114       num_rects = 0;
    115       include = false;
    116    }
    117    for (i = 0; i < num_rects; i++) {
    118       const struct gl_scissor_rect *rect = &scissor->WindowRects[i];
    119       new_rects[i].minx = MAX2(rect->X, 0);
    120       new_rects[i].miny = MAX2(rect->Y, 0);
    121       new_rects[i].maxx = MAX2(rect->X + rect->Width, 0);
    122       new_rects[i].maxy = MAX2(rect->Y + rect->Height, 0);
    123    }
    124    if (num_rects > 0 && memcmp(new_rects, st->state.window_rects.rects,
    125                                num_rects * sizeof(struct pipe_scissor_state))) {
    126       memcpy(st->state.window_rects.rects, new_rects,
    127              num_rects * sizeof(struct pipe_scissor_state));
    128       changed = true;
    129    }
    130    if (st->state.window_rects.num != num_rects) {
    131       st->state.window_rects.num = num_rects;
    132       changed = true;
    133    }
    134    if (st->state.window_rects.include != include) {
    135       st->state.window_rects.include = include;
    136       changed = true;
    137    }
    138    if (changed)
    139       st->pipe->set_window_rectangles(
    140             st->pipe, include, num_rects, new_rects);
    141 }
    142 
    143 const struct st_tracked_state st_update_scissor = {
    144    update_scissor					/* update */
    145 };
    146 
    147 const struct st_tracked_state st_update_window_rectangles = {
    148    update_window_rectangles				/* update */
    149 };
    150