~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/mesa/main/scissor.c

  • Committer: mmach
  • Date: 2022-09-22 19:56:13 UTC
  • Revision ID: netbit73@gmail.com-20220922195613-wtik9mmy20tmor0i
2022-09-22 21:17:09

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Mesa 3-D graphics library
3
 
 *
4
 
 * Copyright (C) 1999-2007  Brian Paul   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 "Software"),
8
 
 * to deal in the Software without restriction, including without limitation
9
 
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
 
 * and/or sell copies of the Software, and to permit persons to whom the
11
 
 * Software is furnished to do so, subject to the following conditions:
12
 
 *
13
 
 * The above copyright notice and this permission notice shall be included
14
 
 * in all copies or substantial portions of the Software.
15
 
 *
16
 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17
 
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19
 
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
 
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
 
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
 
 * OTHER DEALINGS IN THE SOFTWARE.
23
 
 */
24
 
 
25
 
 
26
 
#include "main/glheader.h"
27
 
#include "main/context.h"
28
 
#include "main/enums.h"
29
 
#include "main/mtypes.h"
30
 
#include "main/scissor.h"
31
 
#include "api_exec_decl.h"
32
 
 
33
 
#include "state_tracker/st_cb_bitmap.h"
34
 
#include "state_tracker/st_context.h"
35
 
 
36
 
/**
37
 
 * Set scissor rectangle data directly in ScissorArray
38
 
 *
39
 
 * This is an internal function that performs no error checking on the
40
 
 * supplied data.  It also does \b not call \c dd_function_table::Scissor.
41
 
 *
42
 
 * \sa _mesa_set_scissor
43
 
 */
44
 
static void
45
 
set_scissor_no_notify(struct gl_context *ctx, unsigned idx,
46
 
                      GLint x, GLint y, GLsizei width, GLsizei height)
47
 
{
48
 
   if (x == ctx->Scissor.ScissorArray[idx].X &&
49
 
       y == ctx->Scissor.ScissorArray[idx].Y &&
50
 
       width == ctx->Scissor.ScissorArray[idx].Width &&
51
 
       height == ctx->Scissor.ScissorArray[idx].Height)
52
 
      return;
53
 
 
54
 
   if (ctx->Scissor.EnableFlags)
55
 
      st_flush_bitmap_cache(st_context(ctx));
56
 
 
57
 
   FLUSH_VERTICES(ctx, 0, GL_SCISSOR_BIT);
58
 
   ctx->NewDriverState |= ST_NEW_SCISSOR;
59
 
 
60
 
   ctx->Scissor.ScissorArray[idx].X = x;
61
 
   ctx->Scissor.ScissorArray[idx].Y = y;
62
 
   ctx->Scissor.ScissorArray[idx].Width = width;
63
 
   ctx->Scissor.ScissorArray[idx].Height = height;
64
 
}
65
 
 
66
 
static void
67
 
scissor(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei height)
68
 
{
69
 
   unsigned i;
70
 
 
71
 
   /* The GL_ARB_viewport_array spec says:
72
 
    *
73
 
    *     "Scissor sets the scissor rectangle for all viewports to the same
74
 
    *     values and is equivalent (assuming no errors are generated) to:
75
 
    *
76
 
    *     for (uint i = 0; i < MAX_VIEWPORTS; i++) {
77
 
    *         ScissorIndexed(i, left, bottom, width, height);
78
 
    *     }"
79
 
    *
80
 
    * Set the scissor rectangle for all of the viewports supported by the
81
 
    * implementation, but only signal the driver once at the end.
82
 
    */
83
 
   for (i = 0; i < ctx->Const.MaxViewports; i++)
84
 
      set_scissor_no_notify(ctx, i, x, y, width, height);
85
 
}
86
 
 
87
 
/**
88
 
 * Called via glScissor
89
 
 */
90
 
void GLAPIENTRY
91
 
_mesa_Scissor_no_error(GLint x, GLint y, GLsizei width, GLsizei height)
92
 
{
93
 
   GET_CURRENT_CONTEXT(ctx);
94
 
   scissor(ctx, x, y, width, height);
95
 
}
96
 
 
97
 
void GLAPIENTRY
98
 
_mesa_Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
99
 
{
100
 
   GET_CURRENT_CONTEXT(ctx);
101
 
 
102
 
   if (MESA_VERBOSE & VERBOSE_API)
103
 
      _mesa_debug(ctx, "glScissor %d %d %d %d\n", x, y, width, height);
104
 
 
105
 
   if (width < 0 || height < 0) {
106
 
      _mesa_error( ctx, GL_INVALID_VALUE, "glScissor" );
107
 
      return;
108
 
   }
109
 
 
110
 
   scissor(ctx, x, y, width, height);
111
 
}
112
 
 
113
 
 
114
 
/**
115
 
 * Define the scissor box.
116
 
 *
117
 
 * \param x, y coordinates of the scissor box lower-left corner.
118
 
 * \param width width of the scissor box.
119
 
 * \param height height of the scissor box.
120
 
 *
121
 
 * \sa glScissor().
122
 
 *
123
 
 * Verifies the parameters and updates __struct gl_contextRec::Scissor. On a
124
 
 * change flushes the vertices and notifies the driver via
125
 
 * the dd_function_table::Scissor callback.
126
 
 */
127
 
void
128
 
_mesa_set_scissor(struct gl_context *ctx, unsigned idx,
129
 
                  GLint x, GLint y, GLsizei width, GLsizei height)
130
 
{
131
 
   set_scissor_no_notify(ctx, idx, x, y, width, height);
132
 
}
133
 
 
134
 
static void
135
 
scissor_array(struct gl_context *ctx, GLuint first, GLsizei count,
136
 
              struct gl_scissor_rect *rect)
137
 
{
138
 
   for (GLsizei i = 0; i < count; i++) {
139
 
      set_scissor_no_notify(ctx, i + first, rect[i].X, rect[i].Y,
140
 
                            rect[i].Width, rect[i].Height);
141
 
   }
142
 
}
143
 
 
144
 
/**
145
 
 * Define count scissor boxes starting at index.
146
 
 *
147
 
 * \param index  index of first scissor records to set
148
 
 * \param count  number of scissor records to set
149
 
 * \param x, y   pointer to array of struct gl_scissor_rects
150
 
 *
151
 
 * \sa glScissorArrayv().
152
 
 *
153
 
 * Verifies the parameters and call set_scissor_no_notify to do the work.
154
 
 */
155
 
void GLAPIENTRY
156
 
_mesa_ScissorArrayv_no_error(GLuint first, GLsizei count, const GLint *v)
157
 
{
158
 
   GET_CURRENT_CONTEXT(ctx);
159
 
 
160
 
   struct gl_scissor_rect *p = (struct gl_scissor_rect *)v;
161
 
   scissor_array(ctx, first, count, p);
162
 
}
163
 
 
164
 
void GLAPIENTRY
165
 
_mesa_ScissorArrayv(GLuint first, GLsizei count, const GLint *v)
166
 
{
167
 
   int i;
168
 
   struct gl_scissor_rect *p = (struct gl_scissor_rect *) v;
169
 
   GET_CURRENT_CONTEXT(ctx);
170
 
 
171
 
   if ((first + count) > ctx->Const.MaxViewports) {
172
 
      _mesa_error(ctx, GL_INVALID_VALUE,
173
 
                  "glScissorArrayv: first (%d) + count (%d) >= MaxViewports (%d)",
174
 
                  first, count, ctx->Const.MaxViewports);
175
 
      return;
176
 
   }
177
 
 
178
 
   /* Verify width & height */
179
 
   for (i = 0; i < count; i++) {
180
 
      if (p[i].Width < 0 || p[i].Height < 0) {
181
 
         _mesa_error(ctx, GL_INVALID_VALUE,
182
 
                     "glScissorArrayv: index (%d) width or height < 0 (%d, %d)",
183
 
                     i, p[i].Width, p[i].Height);
184
 
         return;
185
 
      }
186
 
   }
187
 
 
188
 
   scissor_array(ctx, first, count, p);
189
 
}
190
 
 
191
 
/**
192
 
 * Define the scissor box.
193
 
 *
194
 
 * \param index  index of scissor records to set
195
 
 * \param x, y   coordinates of the scissor box lower-left corner.
196
 
 * \param width  width of the scissor box.
197
 
 * \param height height of the scissor box.
198
 
 *
199
 
 * Verifies the parameters call set_scissor_no_notify to do the work.
200
 
 */
201
 
static void
202
 
scissor_indexed_err(struct gl_context *ctx, GLuint index, GLint left,
203
 
                    GLint bottom, GLsizei width, GLsizei height,
204
 
                    const char *function)
205
 
{
206
 
   if (MESA_VERBOSE & VERBOSE_API)
207
 
      _mesa_debug(ctx, "%s(%d, %d, %d, %d, %d)\n",
208
 
                  function, index, left, bottom, width, height);
209
 
 
210
 
   if (index >= ctx->Const.MaxViewports) {
211
 
      _mesa_error(ctx, GL_INVALID_VALUE,
212
 
                  "%s: index (%d) >= MaxViewports (%d)",
213
 
                  function, index, ctx->Const.MaxViewports);
214
 
      return;
215
 
   }
216
 
 
217
 
   if (width < 0 || height < 0) {
218
 
      _mesa_error(ctx, GL_INVALID_VALUE,
219
 
                  "%s: index (%d) width or height < 0 (%d, %d)",
220
 
                  function, index, width, height);
221
 
      return;
222
 
   }
223
 
 
224
 
   _mesa_set_scissor(ctx, index, left, bottom, width, height);
225
 
}
226
 
 
227
 
void GLAPIENTRY
228
 
_mesa_ScissorIndexed_no_error(GLuint index, GLint left, GLint bottom,
229
 
                              GLsizei width, GLsizei height)
230
 
{
231
 
   GET_CURRENT_CONTEXT(ctx);
232
 
   _mesa_set_scissor(ctx, index, left, bottom, width, height);
233
 
}
234
 
 
235
 
void GLAPIENTRY
236
 
_mesa_ScissorIndexed(GLuint index, GLint left, GLint bottom,
237
 
                     GLsizei width, GLsizei height)
238
 
{
239
 
   GET_CURRENT_CONTEXT(ctx);
240
 
   scissor_indexed_err(ctx, index, left, bottom, width, height,
241
 
                       "glScissorIndexed");
242
 
}
243
 
 
244
 
void GLAPIENTRY
245
 
_mesa_ScissorIndexedv_no_error(GLuint index, const GLint *v)
246
 
{
247
 
   GET_CURRENT_CONTEXT(ctx);
248
 
   _mesa_set_scissor(ctx, index, v[0], v[1], v[2], v[3]);
249
 
}
250
 
 
251
 
void GLAPIENTRY
252
 
_mesa_ScissorIndexedv(GLuint index, const GLint *v)
253
 
{
254
 
   GET_CURRENT_CONTEXT(ctx);
255
 
   scissor_indexed_err(ctx, index, v[0], v[1], v[2], v[3],
256
 
                       "glScissorIndexedv");
257
 
}
258
 
 
259
 
void GLAPIENTRY
260
 
_mesa_WindowRectanglesEXT(GLenum mode, GLsizei count, const GLint *box)
261
 
{
262
 
   int i;
263
 
   struct gl_scissor_rect newval[MAX_WINDOW_RECTANGLES];
264
 
   GET_CURRENT_CONTEXT(ctx);
265
 
 
266
 
   if (MESA_VERBOSE & VERBOSE_API)
267
 
      _mesa_debug(ctx, "glWindowRectanglesEXT(%s, %d, %p)\n",
268
 
                  _mesa_enum_to_string(mode), count, box);
269
 
 
270
 
   if (mode != GL_INCLUSIVE_EXT && mode != GL_EXCLUSIVE_EXT) {
271
 
      _mesa_error(ctx, GL_INVALID_ENUM,
272
 
                  "glWindowRectanglesEXT(invalid mode 0x%x)", mode);
273
 
      return;
274
 
   }
275
 
 
276
 
   if (count < 0) {
277
 
      _mesa_error(ctx, GL_INVALID_VALUE, "glWindowRectanglesEXT(count < 0)");
278
 
      return;
279
 
   }
280
 
 
281
 
   if (count > ctx->Const.MaxWindowRectangles) {
282
 
      _mesa_error(ctx, GL_INVALID_VALUE,
283
 
                  "glWindowRectanglesEXT(count >= MaxWindowRectangles (%d)",
284
 
                  ctx->Const.MaxWindowRectangles);
285
 
      return;
286
 
   }
287
 
 
288
 
   for (i = 0; i < count; i++) {
289
 
      if (box[2] < 0 || box[3] < 0) {
290
 
         _mesa_error(ctx, GL_INVALID_VALUE,
291
 
                     "glWindowRectanglesEXT(box %d: w < 0 || h < 0)", i);
292
 
         return;
293
 
      }
294
 
      newval[i].X = box[0];
295
 
      newval[i].Y = box[1];
296
 
      newval[i].Width = box[2];
297
 
      newval[i].Height = box[3];
298
 
      box += 4;
299
 
   }
300
 
 
301
 
   st_flush_bitmap_cache(st_context(ctx));
302
 
 
303
 
   FLUSH_VERTICES(ctx, 0, GL_SCISSOR_BIT);
304
 
   ctx->NewDriverState |= ST_NEW_WINDOW_RECTANGLES;
305
 
 
306
 
   memcpy(ctx->Scissor.WindowRects, newval,
307
 
          sizeof(struct gl_scissor_rect) * count);
308
 
   ctx->Scissor.NumWindowRects = count;
309
 
   ctx->Scissor.WindowRectMode = mode;
310
 
}
311
 
 
312
 
 
313
 
/**
314
 
 * Initialize the context's scissor state.
315
 
 * \param ctx  the GL context.
316
 
 */
317
 
void
318
 
_mesa_init_scissor(struct gl_context *ctx)
319
 
{
320
 
   unsigned i;
321
 
 
322
 
   /* Scissor group */
323
 
   ctx->Scissor.EnableFlags = 0;
324
 
   ctx->Scissor.WindowRectMode = GL_EXCLUSIVE_EXT;
325
 
 
326
 
   /* Note: ctx->Const.MaxViewports may not have been set by the driver yet,
327
 
    * so just initialize all of them.
328
 
    */
329
 
   for (i = 0; i < MAX_VIEWPORTS; i++)
330
 
      set_scissor_no_notify(ctx, i, 0, 0, 0, 0);
331
 
}