1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Mesa 3-D graphics library 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 5bf215546Sopenharmony_ci * 6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 8bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 9bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 11bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 12bf215546Sopenharmony_ci * 13bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 14bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 15bf215546Sopenharmony_ci * Software. 16bf215546Sopenharmony_ci * 17bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE. 24bf215546Sopenharmony_ci */ 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci/** 27bf215546Sopenharmony_ci * \file condrender.c 28bf215546Sopenharmony_ci * Conditional rendering functions 29bf215546Sopenharmony_ci * 30bf215546Sopenharmony_ci * \author Brian Paul 31bf215546Sopenharmony_ci */ 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ci#include "glheader.h" 34bf215546Sopenharmony_ci#include "condrender.h" 35bf215546Sopenharmony_ci#include "enums.h" 36bf215546Sopenharmony_ci#include "mtypes.h" 37bf215546Sopenharmony_ci#include "queryobj.h" 38bf215546Sopenharmony_ci 39bf215546Sopenharmony_ci#include "api_exec_decl.h" 40bf215546Sopenharmony_ci#include "state_tracker/st_cb_bitmap.h" 41bf215546Sopenharmony_ci#include "state_tracker/st_context.h" 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_cistatic void 44bf215546Sopenharmony_ciBeginConditionalRender(struct gl_context *ctx, struct gl_query_object *q, 45bf215546Sopenharmony_ci GLenum mode) 46bf215546Sopenharmony_ci{ 47bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 48bf215546Sopenharmony_ci uint m; 49bf215546Sopenharmony_ci /* Don't invert the condition for rendering by default */ 50bf215546Sopenharmony_ci boolean inverted = FALSE; 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_ci st_flush_bitmap_cache(st); 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_ci switch (mode) { 55bf215546Sopenharmony_ci case GL_QUERY_WAIT: 56bf215546Sopenharmony_ci m = PIPE_RENDER_COND_WAIT; 57bf215546Sopenharmony_ci break; 58bf215546Sopenharmony_ci case GL_QUERY_NO_WAIT: 59bf215546Sopenharmony_ci m = PIPE_RENDER_COND_NO_WAIT; 60bf215546Sopenharmony_ci break; 61bf215546Sopenharmony_ci case GL_QUERY_BY_REGION_WAIT: 62bf215546Sopenharmony_ci m = PIPE_RENDER_COND_BY_REGION_WAIT; 63bf215546Sopenharmony_ci break; 64bf215546Sopenharmony_ci case GL_QUERY_BY_REGION_NO_WAIT: 65bf215546Sopenharmony_ci m = PIPE_RENDER_COND_BY_REGION_NO_WAIT; 66bf215546Sopenharmony_ci break; 67bf215546Sopenharmony_ci case GL_QUERY_WAIT_INVERTED: 68bf215546Sopenharmony_ci m = PIPE_RENDER_COND_WAIT; 69bf215546Sopenharmony_ci inverted = TRUE; 70bf215546Sopenharmony_ci break; 71bf215546Sopenharmony_ci case GL_QUERY_NO_WAIT_INVERTED: 72bf215546Sopenharmony_ci m = PIPE_RENDER_COND_NO_WAIT; 73bf215546Sopenharmony_ci inverted = TRUE; 74bf215546Sopenharmony_ci break; 75bf215546Sopenharmony_ci case GL_QUERY_BY_REGION_WAIT_INVERTED: 76bf215546Sopenharmony_ci m = PIPE_RENDER_COND_BY_REGION_WAIT; 77bf215546Sopenharmony_ci inverted = TRUE; 78bf215546Sopenharmony_ci break; 79bf215546Sopenharmony_ci case GL_QUERY_BY_REGION_NO_WAIT_INVERTED: 80bf215546Sopenharmony_ci m = PIPE_RENDER_COND_BY_REGION_NO_WAIT; 81bf215546Sopenharmony_ci inverted = TRUE; 82bf215546Sopenharmony_ci break; 83bf215546Sopenharmony_ci default: 84bf215546Sopenharmony_ci assert(0 && "bad mode in st_BeginConditionalRender"); 85bf215546Sopenharmony_ci m = PIPE_RENDER_COND_WAIT; 86bf215546Sopenharmony_ci } 87bf215546Sopenharmony_ci 88bf215546Sopenharmony_ci cso_set_render_condition(st->cso_context, q->pq, inverted, m); 89bf215546Sopenharmony_ci} 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_cistatic void 92bf215546Sopenharmony_ciEndConditionalRender(struct gl_context *ctx, struct gl_query_object *q) 93bf215546Sopenharmony_ci{ 94bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 95bf215546Sopenharmony_ci (void) q; 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci st_flush_bitmap_cache(st); 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_ci cso_set_render_condition(st->cso_context, NULL, FALSE, 0); 100bf215546Sopenharmony_ci} 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_cistatic ALWAYS_INLINE void 103bf215546Sopenharmony_cibegin_conditional_render(struct gl_context *ctx, GLuint queryId, GLenum mode, 104bf215546Sopenharmony_ci bool no_error) 105bf215546Sopenharmony_ci{ 106bf215546Sopenharmony_ci struct gl_query_object *q = NULL; 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_ci assert(ctx->Query.CondRenderMode == GL_NONE); 109bf215546Sopenharmony_ci 110bf215546Sopenharmony_ci if (queryId != 0) 111bf215546Sopenharmony_ci q = _mesa_lookup_query_object(ctx, queryId); 112bf215546Sopenharmony_ci 113bf215546Sopenharmony_ci if (!no_error) { 114bf215546Sopenharmony_ci /* Section 2.14 (Conditional Rendering) of the OpenGL 3.0 spec says: 115bf215546Sopenharmony_ci * 116bf215546Sopenharmony_ci * "The error INVALID_VALUE is generated if <id> is not the name of an 117bf215546Sopenharmony_ci * existing query object query." 118bf215546Sopenharmony_ci */ 119bf215546Sopenharmony_ci if (!q) { 120bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_VALUE, 121bf215546Sopenharmony_ci "glBeginConditionalRender(bad queryId=%u)", queryId); 122bf215546Sopenharmony_ci return; 123bf215546Sopenharmony_ci } 124bf215546Sopenharmony_ci assert(q->Id == queryId); 125bf215546Sopenharmony_ci 126bf215546Sopenharmony_ci switch (mode) { 127bf215546Sopenharmony_ci case GL_QUERY_WAIT: 128bf215546Sopenharmony_ci case GL_QUERY_NO_WAIT: 129bf215546Sopenharmony_ci case GL_QUERY_BY_REGION_WAIT: 130bf215546Sopenharmony_ci case GL_QUERY_BY_REGION_NO_WAIT: 131bf215546Sopenharmony_ci break; /* OK */ 132bf215546Sopenharmony_ci case GL_QUERY_WAIT_INVERTED: 133bf215546Sopenharmony_ci case GL_QUERY_NO_WAIT_INVERTED: 134bf215546Sopenharmony_ci case GL_QUERY_BY_REGION_WAIT_INVERTED: 135bf215546Sopenharmony_ci case GL_QUERY_BY_REGION_NO_WAIT_INVERTED: 136bf215546Sopenharmony_ci if (ctx->Extensions.ARB_conditional_render_inverted) 137bf215546Sopenharmony_ci break; /* OK */ 138bf215546Sopenharmony_ci FALLTHROUGH; 139bf215546Sopenharmony_ci default: 140bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_ENUM, "glBeginConditionalRender(mode=%s)", 141bf215546Sopenharmony_ci _mesa_enum_to_string(mode)); 142bf215546Sopenharmony_ci return; 143bf215546Sopenharmony_ci } 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_ci /* Section 2.14 (Conditional Rendering) of the OpenGL 3.0 spec says: 146bf215546Sopenharmony_ci * 147bf215546Sopenharmony_ci * "The error INVALID_OPERATION is generated if <id> is the name of a 148bf215546Sopenharmony_ci * query object with a target other than SAMPLES_PASSED, or <id> is 149bf215546Sopenharmony_ci * the name of a query currently in progress." 150bf215546Sopenharmony_ci */ 151bf215546Sopenharmony_ci if ((q->Target != GL_SAMPLES_PASSED && 152bf215546Sopenharmony_ci q->Target != GL_ANY_SAMPLES_PASSED && 153bf215546Sopenharmony_ci q->Target != GL_ANY_SAMPLES_PASSED_CONSERVATIVE && 154bf215546Sopenharmony_ci q->Target != GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB && 155bf215546Sopenharmony_ci q->Target != GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB) || q->Active) { 156bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginConditionalRender()"); 157bf215546Sopenharmony_ci return; 158bf215546Sopenharmony_ci } 159bf215546Sopenharmony_ci } 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci ctx->Query.CondRenderQuery = q; 162bf215546Sopenharmony_ci ctx->Query.CondRenderMode = mode; 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_ci BeginConditionalRender(ctx, q, mode); 165bf215546Sopenharmony_ci} 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci 168bf215546Sopenharmony_civoid GLAPIENTRY 169bf215546Sopenharmony_ci_mesa_BeginConditionalRender_no_error(GLuint queryId, GLenum mode) 170bf215546Sopenharmony_ci{ 171bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 172bf215546Sopenharmony_ci begin_conditional_render(ctx, queryId, mode, true); 173bf215546Sopenharmony_ci} 174bf215546Sopenharmony_ci 175bf215546Sopenharmony_ci 176bf215546Sopenharmony_civoid GLAPIENTRY 177bf215546Sopenharmony_ci_mesa_BeginConditionalRender(GLuint queryId, GLenum mode) 178bf215546Sopenharmony_ci{ 179bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_ci /* Section 2.14 (Conditional Rendering) of the OpenGL 3.0 spec says: 182bf215546Sopenharmony_ci * 183bf215546Sopenharmony_ci * "If BeginConditionalRender is called while conditional rendering is 184bf215546Sopenharmony_ci * in progress, or if EndConditionalRender is called while conditional 185bf215546Sopenharmony_ci * rendering is not in progress, the error INVALID_OPERATION is 186bf215546Sopenharmony_ci * generated." 187bf215546Sopenharmony_ci */ 188bf215546Sopenharmony_ci if (!ctx->Extensions.NV_conditional_render || ctx->Query.CondRenderQuery) { 189bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginConditionalRender()"); 190bf215546Sopenharmony_ci return; 191bf215546Sopenharmony_ci } 192bf215546Sopenharmony_ci 193bf215546Sopenharmony_ci begin_conditional_render(ctx, queryId, mode, false); 194bf215546Sopenharmony_ci} 195bf215546Sopenharmony_ci 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_cistatic void 198bf215546Sopenharmony_ciend_conditional_render(struct gl_context *ctx) 199bf215546Sopenharmony_ci{ 200bf215546Sopenharmony_ci FLUSH_VERTICES(ctx, 0, 0); 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ci EndConditionalRender(ctx, ctx->Query.CondRenderQuery); 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci ctx->Query.CondRenderQuery = NULL; 205bf215546Sopenharmony_ci ctx->Query.CondRenderMode = GL_NONE; 206bf215546Sopenharmony_ci} 207bf215546Sopenharmony_ci 208bf215546Sopenharmony_ci 209bf215546Sopenharmony_civoid APIENTRY 210bf215546Sopenharmony_ci_mesa_EndConditionalRender_no_error(void) 211bf215546Sopenharmony_ci{ 212bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 213bf215546Sopenharmony_ci end_conditional_render(ctx); 214bf215546Sopenharmony_ci} 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_civoid APIENTRY 218bf215546Sopenharmony_ci_mesa_EndConditionalRender(void) 219bf215546Sopenharmony_ci{ 220bf215546Sopenharmony_ci GET_CURRENT_CONTEXT(ctx); 221bf215546Sopenharmony_ci 222bf215546Sopenharmony_ci if (!ctx->Extensions.NV_conditional_render || !ctx->Query.CondRenderQuery) { 223bf215546Sopenharmony_ci _mesa_error(ctx, GL_INVALID_OPERATION, "glEndConditionalRender()"); 224bf215546Sopenharmony_ci return; 225bf215546Sopenharmony_ci } 226bf215546Sopenharmony_ci 227bf215546Sopenharmony_ci end_conditional_render(ctx); 228bf215546Sopenharmony_ci} 229bf215546Sopenharmony_ci 230bf215546Sopenharmony_ci 231bf215546Sopenharmony_ci/** 232bf215546Sopenharmony_ci * This function is called by software rendering commands (all point, 233bf215546Sopenharmony_ci * line triangle drawing, glClear, glDrawPixels, glCopyPixels, and 234bf215546Sopenharmony_ci * glBitmap, glBlitFramebuffer) to determine if subsequent drawing 235bf215546Sopenharmony_ci * commands should be 236bf215546Sopenharmony_ci * executed or discarded depending on the current conditional 237bf215546Sopenharmony_ci * rendering state. Ideally, this check would be implemented by the 238bf215546Sopenharmony_ci * GPU when doing hardware rendering. XXX should this function be 239bf215546Sopenharmony_ci * called via a new driver hook? 240bf215546Sopenharmony_ci * 241bf215546Sopenharmony_ci * \return GL_TRUE if we should render, GL_FALSE if we should discard 242bf215546Sopenharmony_ci */ 243bf215546Sopenharmony_ciGLboolean 244bf215546Sopenharmony_ci_mesa_check_conditional_render(struct gl_context *ctx) 245bf215546Sopenharmony_ci{ 246bf215546Sopenharmony_ci struct gl_query_object *q = ctx->Query.CondRenderQuery; 247bf215546Sopenharmony_ci 248bf215546Sopenharmony_ci if (!q) { 249bf215546Sopenharmony_ci /* no query in progress - draw normally */ 250bf215546Sopenharmony_ci return GL_TRUE; 251bf215546Sopenharmony_ci } 252bf215546Sopenharmony_ci 253bf215546Sopenharmony_ci switch (ctx->Query.CondRenderMode) { 254bf215546Sopenharmony_ci case GL_QUERY_BY_REGION_WAIT: 255bf215546Sopenharmony_ci FALLTHROUGH; 256bf215546Sopenharmony_ci case GL_QUERY_WAIT: 257bf215546Sopenharmony_ci if (!q->Ready) { 258bf215546Sopenharmony_ci _mesa_wait_query(ctx, q); 259bf215546Sopenharmony_ci } 260bf215546Sopenharmony_ci return q->Result > 0; 261bf215546Sopenharmony_ci case GL_QUERY_BY_REGION_WAIT_INVERTED: 262bf215546Sopenharmony_ci FALLTHROUGH; 263bf215546Sopenharmony_ci case GL_QUERY_WAIT_INVERTED: 264bf215546Sopenharmony_ci if (!q->Ready) { 265bf215546Sopenharmony_ci _mesa_wait_query(ctx, q); 266bf215546Sopenharmony_ci } 267bf215546Sopenharmony_ci return q->Result == 0; 268bf215546Sopenharmony_ci case GL_QUERY_BY_REGION_NO_WAIT: 269bf215546Sopenharmony_ci FALLTHROUGH; 270bf215546Sopenharmony_ci case GL_QUERY_NO_WAIT: 271bf215546Sopenharmony_ci if (!q->Ready) 272bf215546Sopenharmony_ci _mesa_check_query(ctx, q); 273bf215546Sopenharmony_ci return q->Ready ? (q->Result > 0) : GL_TRUE; 274bf215546Sopenharmony_ci case GL_QUERY_BY_REGION_NO_WAIT_INVERTED: 275bf215546Sopenharmony_ci FALLTHROUGH; 276bf215546Sopenharmony_ci case GL_QUERY_NO_WAIT_INVERTED: 277bf215546Sopenharmony_ci if (!q->Ready) 278bf215546Sopenharmony_ci _mesa_check_query(ctx, q); 279bf215546Sopenharmony_ci return q->Ready ? (q->Result == 0) : GL_TRUE; 280bf215546Sopenharmony_ci default: 281bf215546Sopenharmony_ci _mesa_problem(ctx, "Bad cond render mode %s in " 282bf215546Sopenharmony_ci " _mesa_check_conditional_render()", 283bf215546Sopenharmony_ci _mesa_enum_to_string(ctx->Query.CondRenderMode)); 284bf215546Sopenharmony_ci return GL_TRUE; 285bf215546Sopenharmony_ci } 286bf215546Sopenharmony_ci} 287