X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fstate_tracker%2Fst_atom_scissor.c;h=a87d02941ca26e0c77f56444c0739254922067f9;hb=a331d7d1cdfdc971f707fb6b1f71edbad622c804;hp=3fd59e1945c2677b2de1cf8bbc3fd3388c7f50a8;hpb=608e14c5b265d331f89959b8e477796ac21c297c;p=mesa.git diff --git a/src/mesa/state_tracker/st_atom_scissor.c b/src/mesa/state_tracker/st_atom_scissor.c index 3fd59e1945c..a87d02941ca 100644 --- a/src/mesa/state_tracker/st_atom_scissor.c +++ b/src/mesa/state_tracker/st_atom_scissor.c @@ -1,6 +1,6 @@ /************************************************************************** * - * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2007 VMware, Inc. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -18,7 +18,7 @@ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -27,10 +27,12 @@ /* * Authors: - * Keith Whitwell + * Keith Whitwell */ +#include "main/macros.h" +#include "main/framebuffer.h" #include "st_context.h" #include "pipe/p_context.h" #include "st_atom.h" @@ -39,54 +41,105 @@ /** * Scissor depends on the scissor box, and the framebuffer dimensions. */ -static void -update_scissor( struct st_context *st ) +void +st_update_scissor( struct st_context *st ) { - struct pipe_scissor_state scissor; - const struct gl_framebuffer *fb = st->ctx->DrawBuffer; + struct pipe_scissor_state scissor[PIPE_MAX_VIEWPORTS]; + const struct gl_context *ctx = st->ctx; + const struct gl_framebuffer *fb = ctx->DrawBuffer; + const unsigned int fb_width = _mesa_geometric_width(fb); + const unsigned int fb_height = _mesa_geometric_height(fb); GLint miny, maxy; + unsigned i; + bool changed = false; - scissor.minx = 0; - scissor.miny = 0; - scissor.maxx = fb->Width; - scissor.maxy = fb->Height; + for (i = 0 ; i < st->state.num_viewports; i++) { + scissor[i].minx = 0; + scissor[i].miny = 0; + scissor[i].maxx = fb_width; + scissor[i].maxy = fb_height; - if (st->ctx->Scissor.Enabled) { - if ((GLuint)st->ctx->Scissor.X > scissor.minx) - scissor.minx = st->ctx->Scissor.X; - if ((GLuint)st->ctx->Scissor.Y > scissor.miny) - scissor.miny = st->ctx->Scissor.Y; + if (ctx->Scissor.EnableFlags & (1 << i)) { + /* need to be careful here with xmax or ymax < 0 */ + GLint xmax = MAX2(0, ctx->Scissor.ScissorArray[i].X + ctx->Scissor.ScissorArray[i].Width); + GLint ymax = MAX2(0, ctx->Scissor.ScissorArray[i].Y + ctx->Scissor.ScissorArray[i].Height); - if ((GLuint)st->ctx->Scissor.X + st->ctx->Scissor.Width < scissor.maxx) - scissor.maxx = st->ctx->Scissor.X + st->ctx->Scissor.Width; - if ((GLuint)st->ctx->Scissor.Y + st->ctx->Scissor.Height < scissor.maxy) - scissor.maxy = st->ctx->Scissor.Y + st->ctx->Scissor.Height; + if (ctx->Scissor.ScissorArray[i].X > (GLint)scissor[i].minx) + scissor[i].minx = ctx->Scissor.ScissorArray[i].X; + if (ctx->Scissor.ScissorArray[i].Y > (GLint)scissor[i].miny) + scissor[i].miny = ctx->Scissor.ScissorArray[i].Y; - /* check for null space */ - if (scissor.minx >= scissor.maxx || scissor.miny >= scissor.maxy) - scissor.minx = scissor.miny = scissor.maxx = scissor.maxy = 0; + if (xmax < (GLint) scissor[i].maxx) + scissor[i].maxx = xmax; + if (ymax < (GLint) scissor[i].maxy) + scissor[i].maxy = ymax; + + /* check for null space */ + if (scissor[i].minx >= scissor[i].maxx || scissor[i].miny >= scissor[i].maxy) + scissor[i].minx = scissor[i].miny = scissor[i].maxx = scissor[i].maxy = 0; + } + + /* Now invert Y if needed. + * Gallium drivers use the convention Y=0=top for surfaces. + */ + if (st->state.fb_orientation == Y_0_TOP) { + miny = fb->Height - scissor[i].maxy; + maxy = fb->Height - scissor[i].miny; + scissor[i].miny = miny; + scissor[i].maxy = maxy; + } + + if (memcmp(&scissor[i], &st->state.scissor[i], sizeof(scissor[0])) != 0) { + /* state has changed */ + st->state.scissor[i] = scissor[i]; /* struct copy */ + changed = true; + } } - /* Now invert Y. Pipe drivers use the convention Y=0=top for surfaces - */ - miny = fb->Height - scissor.maxy; - maxy = fb->Height - scissor.miny; - scissor.miny = miny; - scissor.maxy = maxy; + if (changed) { + struct pipe_context *pipe = st->pipe; - if (memcmp(&scissor, &st->state.scissor, sizeof(scissor)) != 0) { - /* state has changed */ - st->state.scissor = scissor; /* struct copy */ - st->pipe->set_scissor_state(st->pipe, &scissor); /* activate */ + pipe->set_scissor_states(pipe, 0, st->state.num_viewports, scissor); } } +void +st_update_window_rectangles(struct st_context *st) +{ + struct pipe_scissor_state new_rects[PIPE_MAX_WINDOW_RECTANGLES]; + const struct gl_context *ctx = st->ctx; + const struct gl_scissor_attrib *scissor = &ctx->Scissor; + unsigned i; + bool changed = false; + unsigned num_rects = scissor->NumWindowRects; + bool include = scissor->WindowRectMode == GL_INCLUSIVE_EXT; -const struct st_tracked_state st_update_scissor = { - "st_update_scissor", /* name */ - { /* dirty */ - (_NEW_SCISSOR | _NEW_BUFFERS), /* mesa */ - 0, /* st */ - }, - update_scissor /* update */ -}; + if (ctx->DrawBuffer == ctx->WinSysDrawBuffer) { + num_rects = 0; + include = false; + } + for (i = 0; i < num_rects; i++) { + const struct gl_scissor_rect *rect = &scissor->WindowRects[i]; + new_rects[i].minx = MAX2(rect->X, 0); + new_rects[i].miny = MAX2(rect->Y, 0); + new_rects[i].maxx = MAX2(rect->X + rect->Width, 0); + new_rects[i].maxy = MAX2(rect->Y + rect->Height, 0); + } + if (num_rects > 0 && memcmp(new_rects, st->state.window_rects.rects, + num_rects * sizeof(struct pipe_scissor_state))) { + memcpy(st->state.window_rects.rects, new_rects, + num_rects * sizeof(struct pipe_scissor_state)); + changed = true; + } + if (st->state.window_rects.num != num_rects) { + st->state.window_rects.num = num_rects; + changed = true; + } + if (st->state.window_rects.include != include) { + st->state.window_rects.include = include; + changed = true; + } + if (changed) + st->pipe->set_window_rectangles( + st->pipe, include, num_rects, new_rects); +}