r300: OQ rework
authorDave Airlie <airlied@redhat.com>
Sun, 16 Aug 2009 08:42:24 +0000 (18:42 +1000)
committerDave Airlie <airlied@redhat.com>
Tue, 18 Aug 2009 10:10:50 +0000 (20:10 +1000)
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.

17 files changed:
src/mesa/drivers/dri/r300/Makefile
src/mesa/drivers/dri/r300/r300_cmdbuf.c
src/mesa/drivers/dri/r300/r300_context.c
src/mesa/drivers/dri/r300/r300_context.h
src/mesa/drivers/dri/r300/r300_draw.c
src/mesa/drivers/dri/r300/r300_ioctl.c
src/mesa/drivers/dri/r300/r300_queryobj.c [deleted file]
src/mesa/drivers/dri/r300/r300_queryobj.h [deleted file]
src/mesa/drivers/dri/r300/r300_render.c
src/mesa/drivers/dri/r300/r300_state.c
src/mesa/drivers/dri/r300/radeon_queryobj.c [new symlink]
src/mesa/drivers/dri/r300/radeon_queryobj.h [new symlink]
src/mesa/drivers/dri/radeon/radeon_common.c
src/mesa/drivers/dri/radeon/radeon_common_context.c
src/mesa/drivers/dri/radeon/radeon_common_context.h
src/mesa/drivers/dri/radeon/radeon_queryobj.c [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_queryobj.h [new file with mode: 0644]

index 77b3d168f342854b3721dcb8918b984faf54b8c5..188efcb7a0754a99e8af70af2d04a709a61d5c25 100644 (file)
@@ -37,7 +37,8 @@ RADEON_COMMON_SOURCES = \
        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 \
@@ -54,7 +55,6 @@ DRIVER_SOURCES = \
                 r300_shader.c \
                 r300_emit.c \
                 r300_swtcl.c \
-                r300_queryobj.c \
                 $(RADEON_COMMON_SOURCES) \
                 $(EGL_SOURCES) \
                 $(CS_SOURCES)
index 9042bbc1d77422c72f36627dd739f17ce801ca91..1ca9eacda100eb43d18134e1be326e07f0ad6da5 100644 (file)
@@ -54,6 +54,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #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.
@@ -793,6 +794,17 @@ void r300InitCmdBuf(r300ContextPtr r300)
        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;
 
index 91fa77a169058deea8d7b6a9cf4ad6831ac382a2..7508de6fe185c86a6967be4d397df8fc62f2c0cb 100644 (file)
@@ -64,11 +64,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #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"
@@ -234,6 +233,85 @@ static void r300_fallback(GLcontext *ctx, GLuint bit, GLboolean mode)
                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;
@@ -242,6 +320,12 @@ static void r300_init_vtbl(radeonContextPtr radeon)
        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)
@@ -361,8 +445,7 @@ static void r300InitGLExtensions(GLcontext *ctx)
                _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");
        }
 }
@@ -389,6 +472,7 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual,
 
        r300ParseOptions(r300, screen);
 
+       r300->radeon.radeonScreen = screen;
        r300_init_vtbl(&r300->radeon);
 
        _mesa_init_driver_functions(&functions);
@@ -396,7 +480,7 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual,
        r300InitStateFuncs(&functions);
        r300InitTextureFuncs(&functions);
        r300InitShaderFuncs(&functions);
-       r300InitQueryObjFunctions(&functions);
+       radeonInitQueryObjFunctions(&functions);
        radeonInitBufferObjectFuncs(&functions);
 
        if (!radeonInitContext(&r300->radeon, &functions,
@@ -453,8 +537,6 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual,
 
        r300InitGLExtensions(ctx);
 
-       make_empty_list(&r300->query.not_flushed_head);
-
        return GL_TRUE;
 }
 
index 3ba34266084e852b922283b26edcb8e1cb6a5fd4..65e0d4661134461f3090d12b946dc737c7bd83f1 100644 (file)
@@ -290,6 +290,12 @@ typedef struct r300_context *r300ContextPtr;
 #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.
  */
@@ -380,7 +386,6 @@ struct r300_hw_state {
                struct radeon_state_atom border_color;
        } tex;
        struct radeon_state_atom txe;   /* tex enable (4104) */
-
        radeonTexObj *textures[R300_MAX_TEXTURE_UNITS];
 };
 
@@ -505,15 +510,6 @@ struct r300_index_buffer {
        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.
@@ -549,12 +545,6 @@ struct r300_context {
        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;
 };
 
index d524d60299847b9e7746a40dd98f988114806974..239cfe112383e59aec44d79ab952d11a323b4b59 100644 (file)
@@ -36,7 +36,6 @@
 #include "r300_context.h"
 #include "r300_emit.h"
 #include "r300_render.h"
-#include "r300_queryobj.h"
 #include "r300_state.h"
 #include "r300_tex.h"
 
@@ -583,16 +582,12 @@ static GLboolean r300TryDrawPrims(GLcontext *ctx,
        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;
index da801f42e4c80f21a3907097e75fb1818237d8e2..7ab6928247a769727e4d600d0b88666122fd63fc 100644 (file)
@@ -57,7 +57,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "radeon_reg.h"
 #include "r300_emit.h"
 #include "r300_context.h"
-#include "r300_queryobj.h"
 
 #include "vblank.h"
 
@@ -755,19 +754,9 @@ static void r300Clear(GLcontext * ctx, GLbitfield mask)
        }
 }
 
-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;
 }
diff --git a/src/mesa/drivers/dri/r300/r300_queryobj.c b/src/mesa/drivers/dri/r300/r300_queryobj.c
deleted file mode 100644 (file)
index df1fb32..0000000
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * 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;
-}
diff --git a/src/mesa/drivers/dri/r300/r300_queryobj.h b/src/mesa/drivers/dri/r300/r300_queryobj.h
deleted file mode 100644 (file)
index f301f0b..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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);
index 45330cda3c11ad36effcff43e498ac747c403b9e..e1a6fae57f380c326fc73e5119689a5ff01518b5 100644 (file)
@@ -76,7 +76,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "r300_tex.h"
 #include "r300_emit.h"
 #include "r300_fragprog_common.h"
-#include "r300_queryobj.h"
 #include "r300_swtcl.h"
 
 /**
index 6081c337864244e523c6f3e481cbbe82ceef69ed..ce0666b90193efad559a5a16e8d8665202aad277 100644 (file)
@@ -471,7 +471,7 @@ static void r300SetEarlyZState(GLcontext * ctx)
                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]) {
diff --git a/src/mesa/drivers/dri/r300/radeon_queryobj.c b/src/mesa/drivers/dri/r300/radeon_queryobj.c
new file mode 120000 (symlink)
index 0000000..1d6ebc1
--- /dev/null
@@ -0,0 +1 @@
+../radeon/radeon_queryobj.c
\ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/radeon_queryobj.h b/src/mesa/drivers/dri/r300/radeon_queryobj.h
new file mode 120000 (symlink)
index 0000000..8f6f842
--- /dev/null
@@ -0,0 +1 @@
+../radeon/radeon_queryobj.h
\ No newline at end of file
index 0614c894595b2d2f8acc61f9e965a58c1d5a6839..0e9a1ae5d8179c8f7b2c4aa68da12a31162f76ce 100644 (file)
@@ -83,6 +83,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "radeon_lock.h"
 #include "radeon_drm.h"
 #include "radeon_mipmap_tree.h"
+#include "radeon_queryobj.h"
 
 #define DEBUG_CMDBUF         0
 
@@ -1072,6 +1073,9 @@ void radeonFlush(GLcontext *ctx)
                        }
                }
        }
+
+       make_empty_list(&radeon->query.not_flushed_head);
+
 }
 
 /* Make sure all commands have been sent to the hardware and have
@@ -1128,6 +1132,8 @@ int rcommonFlushCmdBufLocked(radeonContextPtr rmesa, const char *caller)
                        __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;
index c0abcbfa21e3a321565c40c61536a0611e9ae74a..35622099bf0665d94c2d072a010f5f444dac07c7 100644 (file)
@@ -263,6 +263,8 @@ GLboolean radeonInitContext(radeonContextPtr radeon,
                radeon->texture_compressed_row_align = 64;
        }
 
+       make_empty_list(&radeon->query.not_flushed_head);
+
        return GL_TRUE;
 }
 
index ee46c1f81a668c17fc452ef43fc9a94a87df981e..a9480cd2e4c47a70e68767f4ddbb366aa09afc14 100644 (file)
@@ -163,6 +163,7 @@ struct radeon_hw_state {
        /* 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;
 };
 
@@ -254,6 +255,17 @@ static INLINE radeonTexObj* radeon_tex_obj(struct gl_texture_object *texObj)
        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 {
@@ -499,6 +511,12 @@ struct radeon_context {
 
    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);
@@ -508,6 +526,7 @@ struct radeon_context {
           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;
 };
 
@@ -523,7 +542,6 @@ static inline __DRIdrawablePrivate* radeon_get_readable(radeonContextPtr radeon)
        return radeon->dri.context->driReadablePriv;
 }
 
-
 /**
  * This function takes a float and packs it into a uint32_t
  */
diff --git a/src/mesa/drivers/dri/radeon/radeon_queryobj.c b/src/mesa/drivers/dri/radeon/radeon_queryobj.c
new file mode 100644 (file)
index 0000000..7025194
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * 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;
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_queryobj.h b/src/mesa/drivers/dri/radeon/radeon_queryobj.h
new file mode 100644 (file)
index 0000000..5e70583
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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);
+}
+