2
* Mesa 3-D graphics library
4
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
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:
13
* The above copyright notice and this permission notice shall be included
14
* in all copies or substantial portions of the Software.
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.
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"
33
#include "state_tracker/st_cb_bitmap.h"
34
#include "state_tracker/st_context.h"
37
* Set scissor rectangle data directly in ScissorArray
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.
42
* \sa _mesa_set_scissor
45
set_scissor_no_notify(struct gl_context *ctx, unsigned idx,
46
GLint x, GLint y, GLsizei width, GLsizei height)
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)
54
if (ctx->Scissor.EnableFlags)
55
st_flush_bitmap_cache(st_context(ctx));
57
FLUSH_VERTICES(ctx, 0, GL_SCISSOR_BIT);
58
ctx->NewDriverState |= ST_NEW_SCISSOR;
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;
67
scissor(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei height)
71
/* The GL_ARB_viewport_array spec says:
73
* "Scissor sets the scissor rectangle for all viewports to the same
74
* values and is equivalent (assuming no errors are generated) to:
76
* for (uint i = 0; i < MAX_VIEWPORTS; i++) {
77
* ScissorIndexed(i, left, bottom, width, height);
80
* Set the scissor rectangle for all of the viewports supported by the
81
* implementation, but only signal the driver once at the end.
83
for (i = 0; i < ctx->Const.MaxViewports; i++)
84
set_scissor_no_notify(ctx, i, x, y, width, height);
88
* Called via glScissor
91
_mesa_Scissor_no_error(GLint x, GLint y, GLsizei width, GLsizei height)
93
GET_CURRENT_CONTEXT(ctx);
94
scissor(ctx, x, y, width, height);
98
_mesa_Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
100
GET_CURRENT_CONTEXT(ctx);
102
if (MESA_VERBOSE & VERBOSE_API)
103
_mesa_debug(ctx, "glScissor %d %d %d %d\n", x, y, width, height);
105
if (width < 0 || height < 0) {
106
_mesa_error( ctx, GL_INVALID_VALUE, "glScissor" );
110
scissor(ctx, x, y, width, height);
115
* Define the scissor box.
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.
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.
128
_mesa_set_scissor(struct gl_context *ctx, unsigned idx,
129
GLint x, GLint y, GLsizei width, GLsizei height)
131
set_scissor_no_notify(ctx, idx, x, y, width, height);
135
scissor_array(struct gl_context *ctx, GLuint first, GLsizei count,
136
struct gl_scissor_rect *rect)
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);
145
* Define count scissor boxes starting at index.
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
151
* \sa glScissorArrayv().
153
* Verifies the parameters and call set_scissor_no_notify to do the work.
156
_mesa_ScissorArrayv_no_error(GLuint first, GLsizei count, const GLint *v)
158
GET_CURRENT_CONTEXT(ctx);
160
struct gl_scissor_rect *p = (struct gl_scissor_rect *)v;
161
scissor_array(ctx, first, count, p);
165
_mesa_ScissorArrayv(GLuint first, GLsizei count, const GLint *v)
168
struct gl_scissor_rect *p = (struct gl_scissor_rect *) v;
169
GET_CURRENT_CONTEXT(ctx);
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);
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);
188
scissor_array(ctx, first, count, p);
192
* Define the scissor box.
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.
199
* Verifies the parameters call set_scissor_no_notify to do the work.
202
scissor_indexed_err(struct gl_context *ctx, GLuint index, GLint left,
203
GLint bottom, GLsizei width, GLsizei height,
204
const char *function)
206
if (MESA_VERBOSE & VERBOSE_API)
207
_mesa_debug(ctx, "%s(%d, %d, %d, %d, %d)\n",
208
function, index, left, bottom, width, height);
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);
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);
224
_mesa_set_scissor(ctx, index, left, bottom, width, height);
228
_mesa_ScissorIndexed_no_error(GLuint index, GLint left, GLint bottom,
229
GLsizei width, GLsizei height)
231
GET_CURRENT_CONTEXT(ctx);
232
_mesa_set_scissor(ctx, index, left, bottom, width, height);
236
_mesa_ScissorIndexed(GLuint index, GLint left, GLint bottom,
237
GLsizei width, GLsizei height)
239
GET_CURRENT_CONTEXT(ctx);
240
scissor_indexed_err(ctx, index, left, bottom, width, height,
245
_mesa_ScissorIndexedv_no_error(GLuint index, const GLint *v)
247
GET_CURRENT_CONTEXT(ctx);
248
_mesa_set_scissor(ctx, index, v[0], v[1], v[2], v[3]);
252
_mesa_ScissorIndexedv(GLuint index, const GLint *v)
254
GET_CURRENT_CONTEXT(ctx);
255
scissor_indexed_err(ctx, index, v[0], v[1], v[2], v[3],
256
"glScissorIndexedv");
260
_mesa_WindowRectanglesEXT(GLenum mode, GLsizei count, const GLint *box)
263
struct gl_scissor_rect newval[MAX_WINDOW_RECTANGLES];
264
GET_CURRENT_CONTEXT(ctx);
266
if (MESA_VERBOSE & VERBOSE_API)
267
_mesa_debug(ctx, "glWindowRectanglesEXT(%s, %d, %p)\n",
268
_mesa_enum_to_string(mode), count, box);
270
if (mode != GL_INCLUSIVE_EXT && mode != GL_EXCLUSIVE_EXT) {
271
_mesa_error(ctx, GL_INVALID_ENUM,
272
"glWindowRectanglesEXT(invalid mode 0x%x)", mode);
277
_mesa_error(ctx, GL_INVALID_VALUE, "glWindowRectanglesEXT(count < 0)");
281
if (count > ctx->Const.MaxWindowRectangles) {
282
_mesa_error(ctx, GL_INVALID_VALUE,
283
"glWindowRectanglesEXT(count >= MaxWindowRectangles (%d)",
284
ctx->Const.MaxWindowRectangles);
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);
294
newval[i].X = box[0];
295
newval[i].Y = box[1];
296
newval[i].Width = box[2];
297
newval[i].Height = box[3];
301
st_flush_bitmap_cache(st_context(ctx));
303
FLUSH_VERTICES(ctx, 0, GL_SCISSOR_BIT);
304
ctx->NewDriverState |= ST_NEW_WINDOW_RECTANGLES;
306
memcpy(ctx->Scissor.WindowRects, newval,
307
sizeof(struct gl_scissor_rect) * count);
308
ctx->Scissor.NumWindowRects = count;
309
ctx->Scissor.WindowRectMode = mode;
314
* Initialize the context's scissor state.
315
* \param ctx the GL context.
318
_mesa_init_scissor(struct gl_context *ctx)
323
ctx->Scissor.EnableFlags = 0;
324
ctx->Scissor.WindowRectMode = GL_EXCLUSIVE_EXT;
326
/* Note: ctx->Const.MaxViewports may not have been set by the driver yet,
327
* so just initialize all of them.
329
for (i = 0; i < MAX_VIEWPORTS; i++)
330
set_scissor_no_notify(ctx, i, 0, 0, 0, 0);