Move to common code base so radeon/r200 can add support for this.
Make OQ start a state emitted like all normal state, and make no-tcl
flushing work in proper places.
Really need a generic post emit space reservation mechanism like max_state
so we can reserve some space for the emit
this code passes demos/arbocclude, piglit occlusion query and
glean occlusion query with TCL and NO-TCL on my rv530.
radeon_mipmap_tree.c \
radeon_span.c \
radeon_fbo.c \
- radeon_buffer_objects.c
+ radeon_buffer_objects.c \
+ radeon_queryobj.c
DRIVER_SOURCES = \
radeon_screen.c \
r300_shader.c \
r300_emit.c \
r300_swtcl.c \
- r300_queryobj.c \
$(RADEON_COMMON_SOURCES) \
$(EGL_SOURCES) \
$(CS_SOURCES)
#include "radeon_mipmap_tree.h"
#include "r300_state.h"
#include "radeon_reg.h"
+#include "radeon_queryobj.h"
/** # of dwords reserved for additional instructions that may need to be written
* during flushing.
r300->hw.tex.border_color.cmd[R300_TEX_CMD_0] =
cmdpacket0(r300->radeon.radeonScreen, R300_TX_BORDER_COLOR_0, 0);
+ radeon_init_query_stateobj(&r300->radeon, R300_QUERYOBJ_CMDSIZE);
+ if (r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV530) {
+ r300->radeon.query.queryobj.cmd[R300_QUERYOBJ_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, RV530_FG_ZBREG_DEST, 1);
+ r300->radeon.query.queryobj.cmd[R300_QUERYOBJ_DATA_0] = RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL;
+ } else {
+ r300->radeon.query.queryobj.cmd[R300_QUERYOBJ_CMD_0] = cmdpacket0(r300->radeon.radeonScreen, R300_SU_REG_DEST, 1);
+ r300->radeon.query.queryobj.cmd[R300_QUERYOBJ_DATA_0] = R300_RASTER_PIPE_SELECT_ALL;
+ }
+ r300->radeon.query.queryobj.cmd[R300_QUERYOBJ_CMD_1] = cmdpacket0(r300->radeon.radeonScreen, R300_ZB_ZPASS_DATA, 1);
+ r300->radeon.query.queryobj.cmd[R300_QUERYOBJ_DATA_1] = 0;
+
r300->radeon.hw.is_dirty = GL_TRUE;
r300->radeon.hw.all_dirty = GL_TRUE;
#include "r300_ioctl.h"
#include "r300_tex.h"
#include "r300_emit.h"
-#include "r300_queryobj.h"
#include "r300_swtcl.h"
#include "radeon_bocs_wrapper.h"
#include "radeon_buffer_objects.h"
-
+#include "radeon_queryobj.h"
#include "vblank.h"
#include "utils.h"
r300->radeon.Fallback &= ~bit;
}
+static void r300_emit_query_finish(radeonContextPtr radeon)
+{
+ r300ContextPtr r300 = (r300ContextPtr)radeon;
+ struct radeon_query_object *query = radeon->query.current;
+ BATCH_LOCALS(radeon);
+
+ BEGIN_BATCH_NO_AUTOSTATE(3 * 2 *r300->num_z_pipes + 2);
+ switch (r300->num_z_pipes) {
+ case 4:
+ OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_3);
+ OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
+ OUT_BATCH_RELOC(0, query->bo, query->curr_offset+3*sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0);
+ case 3:
+ OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_2);
+ OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
+ OUT_BATCH_RELOC(0, query->bo, query->curr_offset+2*sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0);
+ case 2:
+ if (r300->radeon.radeonScreen->chip_family <= CHIP_FAMILY_RV380) {
+ OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_3);
+ } else {
+ OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_1);
+ }
+ OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
+ OUT_BATCH_RELOC(0, query->bo, query->curr_offset+1*sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0);
+ case 1:
+ default:
+ OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_0);
+ OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
+ OUT_BATCH_RELOC(0, query->bo, query->curr_offset, 0, RADEON_GEM_DOMAIN_GTT, 0);
+ break;
+ }
+ OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_ALL);
+ END_BATCH();
+ query->curr_offset += r300->num_z_pipes * sizeof(uint32_t);
+ assert(query->curr_offset < RADEON_QUERY_PAGE_SIZE);
+ query->emitted_begin = GL_FALSE;
+}
+
+static void rv530_emit_query_finish_single_z(radeonContextPtr radeon)
+{
+ r300ContextPtr r300 = (r300ContextPtr)radeon;
+ BATCH_LOCALS(radeon);
+ struct radeon_query_object *query = radeon->query.current;
+
+ BEGIN_BATCH_NO_AUTOSTATE(8);
+ OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0);
+ OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
+ OUT_BATCH_RELOC(0, query->bo, query->curr_offset, 0, RADEON_GEM_DOMAIN_GTT, 0);
+ OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL);
+ END_BATCH();
+
+ query->curr_offset += sizeof(uint32_t);
+ assert(query->curr_offset < RADEON_QUERY_PAGE_SIZE);
+ query->emitted_begin = GL_FALSE;
+}
+
+#if 0
+static void rv530_emit_query_finish_double_z(radeonContextPtr radeon)
+{
+ r300ContextPtr r300 = (r300ContextPtr)radeon;
+ BATCH_LOCALS(radeon);
+ struct radeon_query_object *query = radeon->query.current;
+
+ BEGIN_BATCH_NO_AUTOSTATE(6);
+ OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0);
+ OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
+ OUT_BATCH_RELOC(0, query->bo, query->curr_offset, 0, RADEON_GEM_DOMAIN_GTT, 0);
+ OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_1);
+ OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
+ OUT_BATCH_RELOC(0, query->bo, query->curr_offset + sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0);
+ OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL);
+ END_BATCH();
+
+ query->curr_offset += 2 * sizeof(uint32_t);
+ assert(query->curr_offset < RADEON_QUERY_PAGE_SIZE);
+ query->emitted_begin = GL_FALSE;
+}
+#endif
+
static void r300_init_vtbl(radeonContextPtr radeon)
{
radeon->vtbl.get_lock = r300_get_lock;
radeon->vtbl.swtcl_flush = r300_swtcl_flush;
radeon->vtbl.pre_emit_atoms = r300_vtbl_pre_emit_atoms;
radeon->vtbl.fallback = r300_fallback;
+ if (radeon->radeonScreen->chip_family == CHIP_FAMILY_RV530)
+ /* single Z gives me correct results on my hw need to check if we ever need
+ * double z */
+ radeon->vtbl.emit_query_finish = rv530_emit_query_finish_single_z;
+ else
+ radeon->vtbl.emit_query_finish = r300_emit_query_finish;
}
static void r300InitConstValues(GLcontext *ctx, radeonScreenPtr screen)
_mesa_disable_extension(ctx, "GL_EXT_texture_compression_s3tc");
}
- if (!r300->radeon.radeonScreen->drmSupportsOcclusionQueries ||
- !r300->options.hw_tcl_enabled) {
+ if (!r300->radeon.radeonScreen->drmSupportsOcclusionQueries) {
_mesa_disable_extension(ctx, "GL_ARB_occlusion_query");
}
}
r300ParseOptions(r300, screen);
+ r300->radeon.radeonScreen = screen;
r300_init_vtbl(&r300->radeon);
_mesa_init_driver_functions(&functions);
r300InitStateFuncs(&functions);
r300InitTextureFuncs(&functions);
r300InitShaderFuncs(&functions);
- r300InitQueryObjFunctions(&functions);
+ radeonInitQueryObjFunctions(&functions);
radeonInitBufferObjectFuncs(&functions);
if (!radeonInitContext(&r300->radeon, &functions,
r300InitGLExtensions(ctx);
- make_empty_list(&r300->query.not_flushed_head);
-
return GL_TRUE;
}
#define R300_TEX_CMDSIZE (MAX_TEXTURE_UNITS+1)
*/
+#define R300_QUERYOBJ_CMD_0 0
+#define R300_QUERYOBJ_DATA_0 1
+#define R300_QUERYOBJ_CMD_1 2
+#define R300_QUERYOBJ_DATA_1 3
+#define R300_QUERYOBJ_CMDSIZE 4
+
/**
* Cache for hardware register state.
*/
struct radeon_state_atom border_color;
} tex;
struct radeon_state_atom txe; /* tex enable (4104) */
-
radeonTexObj *textures[R300_MAX_TEXTURE_UNITS];
};
GLuint count;
};
-struct r300_query_object {
- struct gl_query_object Base;
- struct radeon_bo *bo;
- int curr_offset;
- GLboolean emitted_begin;
-
- /* Double linked list of not flushed query objects */
- struct r300_query_object *prev, *next;
-};
/**
* \brief R300 context structure.
uint32_t fallback;
DECLARE_RENDERINPUTS(render_inputs_bitset);
-
- struct {
- struct r300_query_object *current;
- struct r300_query_object not_flushed_head;
- } query;
-
int num_z_pipes;
};
#include "r300_context.h"
#include "r300_emit.h"
#include "r300_render.h"
-#include "r300_queryobj.h"
#include "r300_state.h"
#include "r300_tex.h"
r300EmitCacheFlush(r300);
radeonEmitState(&r300->radeon);
- r300EmitQueryBegin(ctx);
-
for (i = 0; i < nr_prims; ++i) {
r300RunRenderPrimitive(ctx, prim[i].start, prim[i].start + prim[i].count, prim[i].mode);
}
r300EmitCacheFlush(r300);
- r300EmitQueryEnd(ctx);
-
r300FreeData(ctx);
return GL_TRUE;
#include "radeon_reg.h"
#include "r300_emit.h"
#include "r300_context.h"
-#include "r300_queryobj.h"
#include "vblank.h"
}
}
-static void r300Flush(GLcontext *ctx)
-{
- r300ContextPtr r300 = R300_CONTEXT(ctx);
-
- radeonFlush(ctx);
-
- make_empty_list(&r300->query.not_flushed_head);
-}
-
-
void r300InitIoctlFuncs(struct dd_function_table *functions)
{
functions->Clear = r300Clear;
functions->Finish = radeonFinish;
- functions->Flush = r300Flush;
+ functions->Flush = radeonFlush;
}
+++ /dev/null
-/*
- * Copyright © 2008-2009 Maciej Cencora <m.cencora@gmail.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * 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 NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS 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.
- *
- * Authors:
- * Maciej Cencora <m.cencora@gmail.com>
- *
- */
-
-#include "r300_queryobj.h"
-#include "r300_emit.h"
-
-#include "main/imports.h"
-#include "main/simple_list.h"
-
-#define DDEBUG 0
-
-#define PAGE_SIZE 4096
-
-static void r300QueryGetResult(GLcontext *ctx, struct gl_query_object *q)
-{
- struct r300_query_object *query = (struct r300_query_object *)q;
- uint32_t *result;
- int i;
-
- if (DDEBUG) fprintf(stderr, "%s: query id %d, result %d\n", __FUNCTION__, query->Base.Id, (int) query->Base.Result);
-
- radeon_bo_map(query->bo, GL_FALSE);
-
- result = query->bo->ptr;
-
- query->Base.Result = 0;
- for (i = 0; i < query->curr_offset/sizeof(uint32_t); ++i) {
- query->Base.Result += result[i];
- if (DDEBUG) fprintf(stderr, "result[%d] = %d\n", i, result[i]);
- }
-
- radeon_bo_unmap(query->bo);
-}
-
-static struct gl_query_object * r300NewQueryObject(GLcontext *ctx, GLuint id)
-{
- struct r300_query_object *query;
-
- query = _mesa_calloc(sizeof(struct r300_query_object));
-
- query->Base.Id = id;
- query->Base.Result = 0;
- query->Base.Active = GL_FALSE;
- query->Base.Ready = GL_TRUE;
-
- if (DDEBUG) fprintf(stderr, "%s: query id %d\n", __FUNCTION__, query->Base.Id);
-
- return &query->Base;
-}
-
-static void r300DeleteQuery(GLcontext *ctx, struct gl_query_object *q)
-{
- struct r300_query_object *query = (struct r300_query_object *)q;
-
- if (DDEBUG) fprintf(stderr, "%s: query id %d\n", __FUNCTION__, q->Id);
-
- if (query->bo) {
- radeon_bo_unref(query->bo);
- }
-
- _mesa_free(query);
-}
-
-static void r300BeginQuery(GLcontext *ctx, struct gl_query_object *q)
-{
- r300ContextPtr r300 = R300_CONTEXT(ctx);
- struct r300_query_object *query = (struct r300_query_object *)q;
-
- if (DDEBUG) fprintf(stderr, "%s: query id %d\n", __FUNCTION__, q->Id);
-
- assert(r300->query.current == NULL);
-
- if (!query->bo) {
- query->bo = radeon_bo_open(r300->radeon.radeonScreen->bom, 0, PAGE_SIZE, PAGE_SIZE, RADEON_GEM_DOMAIN_GTT, 0);
- }
- query->curr_offset = 0;
-
- r300->query.current = query;
- insert_at_tail(&r300->query.not_flushed_head, query);
-}
-
-static void r300EndQuery(GLcontext *ctx, struct gl_query_object *q)
-{
- r300ContextPtr r300 = R300_CONTEXT(ctx);
-
- if (DDEBUG) fprintf(stderr, "%s: query id %d\n", __FUNCTION__, q->Id);
-
- r300EmitQueryEnd(ctx);
-
- r300->query.current = NULL;
-}
-
-static void r300WaitQuery(GLcontext *ctx, struct gl_query_object *q)
-{
- r300ContextPtr r300 = R300_CONTEXT(ctx);
- struct r300_query_object *tmp, *query = (struct r300_query_object *)q;
-
- /* If the cmdbuf with packets for this query hasn't been flushed yet, do it now */
- {
- GLboolean found = GL_FALSE;
- foreach(tmp, &r300->query.not_flushed_head) {
- if (tmp == query) {
- found = GL_TRUE;
- break;
- }
- }
-
- if (found)
- ctx->Driver.Flush(ctx);
- }
-
- if (DDEBUG) fprintf(stderr, "%s: query id %d, bo %p, offset %d\n", __FUNCTION__, q->Id, query->bo, query->curr_offset);
-
- r300QueryGetResult(ctx, q);
-
- query->Base.Ready = GL_TRUE;
-}
-
-
-/**
- * TODO:
- * should check if bo is idle, bo there's no interface to do it
- * just wait for result now
- */
-static void r300CheckQuery(GLcontext *ctx, struct gl_query_object *q)
-{
- if (DDEBUG) fprintf(stderr, "%s: query id %d\n", __FUNCTION__, q->Id);
-
- r300WaitQuery(ctx, q);
-}
-
-void r300EmitQueryBegin(GLcontext *ctx)
-{
- r300ContextPtr r300 = R300_CONTEXT(ctx);
- struct r300_query_object *query = r300->query.current;
- BATCH_LOCALS(&r300->radeon);
-
- if (!query || query->emitted_begin)
- return;
-
- if (DDEBUG) fprintf(stderr, "%s: query id %d\n", __FUNCTION__, query->Base.Id);
-
- if (r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV530) {
- BEGIN_BATCH_NO_AUTOSTATE(4);
- OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL);
- OUT_BATCH_REGVAL(R300_ZB_ZPASS_DATA, 0);
- END_BATCH();
- } else {
- BEGIN_BATCH_NO_AUTOSTATE(4);
- OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_ALL);
- OUT_BATCH_REGVAL(R300_ZB_ZPASS_DATA, 0);
- END_BATCH();
- }
-
- query->emitted_begin = GL_TRUE;
-}
-
-void r300EmitQueryEnd(GLcontext *ctx)
-{
- r300ContextPtr r300 = R300_CONTEXT(ctx);
- struct r300_query_object *query = r300->query.current;
- BATCH_LOCALS(&r300->radeon);
-
- if (!query || !query->emitted_begin)
- return;
-
- if (DDEBUG) fprintf(stderr, "%s: query id %d, bo %p, offset %d\n", __FUNCTION__, query->Base.Id, query->bo, query->curr_offset);
-
- radeon_cs_space_check_with_bo(r300->radeon.cmdbuf.cs,
- query->bo,
- 0, RADEON_GEM_DOMAIN_GTT);
-
- if (r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV530) {
- BEGIN_BATCH_NO_AUTOSTATE(14);
- OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0);
- OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
- OUT_BATCH_RELOC(0, query->bo, query->curr_offset, 0, RADEON_GEM_DOMAIN_GTT, 0);
- OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_1);
- OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
- OUT_BATCH_RELOC(0, query->bo, query->curr_offset + sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0);
- OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL);
- END_BATCH();
- } else {
- BEGIN_BATCH_NO_AUTOSTATE(3 * 2 *r300->num_z_pipes + 2);
- switch (r300->num_z_pipes) {
- case 4:
- OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_3);
- OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
- OUT_BATCH_RELOC(0, query->bo, query->curr_offset+3*sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0);
- case 3:
- OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_2);
- OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
- OUT_BATCH_RELOC(0, query->bo, query->curr_offset+2*sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0);
- case 2:
- if (r300->radeon.radeonScreen->chip_family <= CHIP_FAMILY_RV380) {
- OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_3);
- } else {
- OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_1);
- }
- OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
- OUT_BATCH_RELOC(0, query->bo, query->curr_offset+1*sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0);
- case 1:
- default:
- OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_0);
- OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
- OUT_BATCH_RELOC(0, query->bo, query->curr_offset, 0, RADEON_GEM_DOMAIN_GTT, 0);
- break;
- }
- OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_ALL);
- END_BATCH();
- }
-
- query->curr_offset += r300->num_z_pipes * sizeof(uint32_t);
- assert(query->curr_offset < PAGE_SIZE);
- query->emitted_begin = GL_FALSE;
-}
-
-void r300InitQueryObjFunctions(struct dd_function_table *functions)
-{
- functions->NewQueryObject = r300NewQueryObject;
- functions->DeleteQuery = r300DeleteQuery;
- functions->BeginQuery = r300BeginQuery;
- functions->EndQuery = r300EndQuery;
- functions->CheckQuery = r300CheckQuery;
- functions->WaitQuery = r300WaitQuery;
-}
+++ /dev/null
-/*
- * Copyright © 2008 Maciej Cencora <m.cencora@gmail.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * 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 NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS 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.
- *
- * Authors:
- * Maciej Cencora <m.cencora@gmail.com>
- *
- */
-
-#include "main/imports.h"
-#include "r300_context.h"
-
-extern void r300EmitQueryBegin(GLcontext *ctx);
-extern void r300EmitQueryEnd(GLcontext *ctx);
-
-extern void r300InitQueryObjFunctions(struct dd_function_table *functions);
#include "r300_tex.h"
#include "r300_emit.h"
#include "r300_fragprog_common.h"
-#include "r300_queryobj.h"
#include "r300_swtcl.h"
/**
topZ = R300_ZTOP_DISABLE;
else if (ctx->FragmentProgram._Current && ctx->FragmentProgram._Current->UsesKill)
topZ = R300_ZTOP_DISABLE;
- else if (r300->query.current)
+ else if (r300->radeon.query.current)
topZ = R300_ZTOP_DISABLE;
if (topZ != r300->hw.zstencil_format.cmd[2]) {
--- /dev/null
+../radeon/radeon_queryobj.c
\ No newline at end of file
--- /dev/null
+../radeon/radeon_queryobj.h
\ No newline at end of file
#include "radeon_lock.h"
#include "radeon_drm.h"
#include "radeon_mipmap_tree.h"
+#include "radeon_queryobj.h"
#define DEBUG_CMDBUF 0
}
}
}
+
+ make_empty_list(&radeon->query.not_flushed_head);
+
}
/* Make sure all commands have been sent to the hardware and have
__FUNCTION__, caller, rmesa->numClipRects);
}
+ radeonEmitQueryEnd(rmesa->glCtx);
+
if (rmesa->cmdbuf.cs->cdw) {
ret = radeon_cs_emit(rmesa->cmdbuf.cs);
rmesa->hw.all_dirty = GL_TRUE;
radeon->texture_compressed_row_align = 64;
}
+ make_empty_list(&radeon->query.not_flushed_head);
+
return GL_TRUE;
}
/* Head of the linked list of state atoms. */
struct radeon_state_atom atomlist;
int max_state_size; /* Number of bytes necessary for a full state emit. */
+ int max_post_flush_size; /* Number of bytes necessary for post flushing emits */
GLboolean is_dirty, all_dirty;
};
return (radeonTexObj*)texObj;
}
+/* occlusion query */
+struct radeon_query_object {
+ struct gl_query_object Base;
+ struct radeon_bo *bo;
+ int curr_offset;
+ GLboolean emitted_begin;
+
+ /* Double linked list of not flushed query objects */
+ struct radeon_query_object *prev, *next;
+};
+
/* Need refcounting on dma buffers:
*/
struct radeon_dma_buffer {
struct dri_metaops meta;
+ struct {
+ struct radeon_query_object *current;
+ struct radeon_query_object not_flushed_head;
+ struct radeon_state_atom queryobj;
+ } query;
+
struct {
void (*get_lock)(radeonContextPtr radeon);
void (*update_viewport_offset)(GLcontext *ctx);
void (*pre_emit_state)(radeonContextPtr rmesa);
void (*fallback)(GLcontext *ctx, GLuint bit, GLboolean mode);
void (*free_context)(GLcontext *ctx);
+ void (*emit_query_finish)(radeonContextPtr radeon);
} vtbl;
};
return radeon->dri.context->driReadablePriv;
}
-
/**
* This function takes a float and packs it into a uint32_t
*/
--- /dev/null
+/*
+ * Copyright © 2008-2009 Maciej Cencora <m.cencora@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Authors:
+ * Maciej Cencora <m.cencora@gmail.com>
+ *
+ */
+#include "radeon_common.h"
+#include "radeon_queryobj.h"
+
+#include "main/imports.h"
+#include "main/simple_list.h"
+
+#define DDEBUG 0
+
+#define PAGE_SIZE 4096
+
+static void radeonQueryGetResult(GLcontext *ctx, struct gl_query_object *q)
+{
+ struct radeon_query_object *query = (struct radeon_query_object *)q;
+ uint32_t *result;
+ int i;
+
+ if (DDEBUG) fprintf(stderr, "%s: query id %d, result %d\n", __FUNCTION__, query->Base.Id, (int) query->Base.Result);
+
+ radeon_bo_map(query->bo, GL_FALSE);
+
+ result = query->bo->ptr;
+
+ query->Base.Result = 0;
+ for (i = 0; i < query->curr_offset/sizeof(uint32_t); ++i) {
+ query->Base.Result += result[i];
+ if (DDEBUG) fprintf(stderr, "result[%d] = %d\n", i, result[i]);
+ }
+
+ radeon_bo_unmap(query->bo);
+}
+
+static struct gl_query_object * radeonNewQueryObject(GLcontext *ctx, GLuint id)
+{
+ struct radeon_query_object *query;
+
+ query = _mesa_calloc(sizeof(struct radeon_query_object));
+
+ query->Base.Id = id;
+ query->Base.Result = 0;
+ query->Base.Active = GL_FALSE;
+ query->Base.Ready = GL_TRUE;
+
+ if (DDEBUG) fprintf(stderr, "%s: query id %d\n", __FUNCTION__, query->Base.Id);
+
+ return &query->Base;
+}
+
+static void radeonDeleteQuery(GLcontext *ctx, struct gl_query_object *q)
+{
+ struct radeon_query_object *query = (struct radeon_query_object *)q;
+
+ if (DDEBUG) fprintf(stderr, "%s: query id %d\n", __FUNCTION__, q->Id);
+
+ if (query->bo) {
+ radeon_bo_unref(query->bo);
+ }
+
+ _mesa_free(query);
+}
+
+static void radeonWaitQuery(GLcontext *ctx, struct gl_query_object *q)
+{
+ radeonContextPtr radeon = RADEON_CONTEXT(ctx);
+ struct radeon_query_object *tmp, *query = (struct radeon_query_object *)q;
+
+ /* If the cmdbuf with packets for this query hasn't been flushed yet, do it now */
+ {
+ GLboolean found = GL_FALSE;
+ foreach(tmp, &radeon->query.not_flushed_head) {
+ if (tmp == query) {
+ found = GL_TRUE;
+ break;
+ }
+ }
+
+ if (found)
+ ctx->Driver.Flush(ctx);
+ }
+
+ if (DDEBUG) fprintf(stderr, "%s: query id %d, bo %p, offset %d\n", __FUNCTION__, q->Id, query->bo, query->curr_offset);
+
+ radeonQueryGetResult(ctx, q);
+
+ query->Base.Ready = GL_TRUE;
+}
+
+
+static void radeonBeginQuery(GLcontext *ctx, struct gl_query_object *q)
+{
+ radeonContextPtr radeon = RADEON_CONTEXT(ctx);
+ struct radeon_query_object *query = (struct radeon_query_object *)q;
+
+ if (DDEBUG) fprintf(stderr, "%s: query id %d\n", __FUNCTION__, q->Id);
+
+ assert(radeon->query.current == NULL);
+
+ if (radeon->dma.flush)
+ radeon->dma.flush(radeon->glCtx);
+
+ if (!query->bo) {
+ query->bo = radeon_bo_open(radeon->radeonScreen->bom, 0, PAGE_SIZE, PAGE_SIZE, RADEON_GEM_DOMAIN_GTT, 0);
+ }
+ query->curr_offset = 0;
+
+ radeon->query.current = query;
+
+ radeon->query.queryobj.dirty = GL_TRUE;
+ insert_at_tail(&radeon->query.not_flushed_head, query);
+
+}
+
+void radeonEmitQueryEnd(GLcontext *ctx)
+{
+ radeonContextPtr radeon = RADEON_CONTEXT(ctx);
+ struct radeon_query_object *query = radeon->query.current;
+
+ if (!query)
+ return;
+
+ if (query->emitted_begin == GL_FALSE)
+ return;
+
+ if (DDEBUG) fprintf(stderr, "%s: query id %d, bo %p, offset %d\n", __FUNCTION__, query->Base.Id, query->bo, query->curr_offset);
+
+ radeon_cs_space_check_with_bo(radeon->cmdbuf.cs,
+ query->bo,
+ 0, RADEON_GEM_DOMAIN_GTT);
+
+ radeon->vtbl.emit_query_finish(radeon);
+}
+
+static void radeonEndQuery(GLcontext *ctx, struct gl_query_object *q)
+{
+ radeonContextPtr radeon = RADEON_CONTEXT(ctx);
+
+ if (DDEBUG) fprintf(stderr, "%s: query id %d\n", __FUNCTION__, q->Id);
+
+ if (radeon->dma.flush)
+ radeon->dma.flush(radeon->glCtx);
+ radeonEmitQueryEnd(ctx);
+
+ radeon->query.current = NULL;
+}
+
+/**
+ * TODO:
+ * should check if bo is idle, bo there's no interface to do it
+ * just wait for result now
+ */
+static void radeonCheckQuery(GLcontext *ctx, struct gl_query_object *q)
+{
+ if (DDEBUG) fprintf(stderr, "%s: query id %d\n", __FUNCTION__, q->Id);
+
+ radeonWaitQuery(ctx, q);
+}
+
+void radeonInitQueryObjFunctions(struct dd_function_table *functions)
+{
+ functions->NewQueryObject = radeonNewQueryObject;
+ functions->DeleteQuery = radeonDeleteQuery;
+ functions->BeginQuery = radeonBeginQuery;
+ functions->EndQuery = radeonEndQuery;
+ functions->CheckQuery = radeonCheckQuery;
+ functions->WaitQuery = radeonWaitQuery;
+}
+
+int radeon_check_query_active(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ radeonContextPtr radeon = RADEON_CONTEXT(ctx);
+ struct radeon_query_object *query = radeon->query.current;
+
+ if (!query || query->emitted_begin)
+ return 0;
+ return atom->cmd_size;
+}
+
+void radeon_emit_queryobj(GLcontext *ctx, struct radeon_state_atom *atom)
+{
+ radeonContextPtr radeon = RADEON_CONTEXT(ctx);
+ BATCH_LOCALS(radeon);
+ int dwords;
+
+ dwords = (*atom->check) (ctx, atom);
+
+ BEGIN_BATCH_NO_AUTOSTATE(dwords);
+ OUT_BATCH_TABLE(atom->cmd, dwords);
+ END_BATCH();
+
+ radeon->query.current->emitted_begin = GL_TRUE;
+}
--- /dev/null
+/*
+ * Copyright © 2008 Maciej Cencora <m.cencora@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Authors:
+ * Maciej Cencora <m.cencora@gmail.com>
+ *
+ */
+
+#include "main/imports.h"
+#include "main/simple_list.h"
+#include "radeon_context.h"
+
+extern void radeonEmitQueryBegin(GLcontext *ctx);
+extern void radeonEmitQueryEnd(GLcontext *ctx);
+
+extern void radeonInitQueryObjFunctions(struct dd_function_table *functions);
+
+#define RADEON_QUERY_PAGE_SIZE 4096
+
+int radeon_check_query_active(GLcontext *ctx, struct radeon_state_atom *atom);
+void radeon_emit_queryobj(GLcontext *ctx, struct radeon_state_atom *atom);
+
+static inline void radeon_init_query_stateobj(radeonContextPtr radeon, int SZ)
+{
+ radeon->query.queryobj.cmd_size = (SZ);
+ radeon->query.queryobj.cmd = (uint32_t*)CALLOC((SZ) * sizeof(uint32_t));
+ radeon->query.queryobj.name = "queryobj";
+ radeon->query.queryobj.idx = 0;
+ radeon->query.queryobj.check = radeon_check_query_active;
+ radeon->query.queryobj.dirty = GL_FALSE;
+ radeon->query.queryobj.emit = radeon_emit_queryobj;
+
+ radeon->hw.max_state_size += (SZ);
+ insert_at_tail(&radeon->hw.atomlist, &radeon->query.queryobj);
+}
+