diff --git a/src/mesa/drivers/dri/r200/r200_context.c b/src/mesa/drivers/dri/r200/r200_context.c
index 3ddb5bf..3ecc27b 100644
--- a/src/mesa/drivers/dri/r200/r200_context.c
+++ b/src/mesa/drivers/dri/r200/r200_context.c
@@ -267,6 +267,7 @@ static void r200_init_vtbl(radeonContextPtr radeon)
    radeon->vtbl.swtcl_flush = r200_swtcl_flush;
    radeon->vtbl.fallback = r200Fallback;
    radeon->vtbl.update_scissor = r200_vtbl_update_scissor;
+   radeon->vtbl.emit_query_begin = NULL;
    radeon->vtbl.emit_query_finish = r200_emit_query_finish;
 }
 
diff --git a/src/mesa/drivers/dri/r300/r300_context.c b/src/mesa/drivers/dri/r300/r300_context.c
index 2c2b16a..76b9032 100644
--- a/src/mesa/drivers/dri/r300/r300_context.c
+++ b/src/mesa/drivers/dri/r300/r300_context.c
@@ -317,6 +317,7 @@ 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;
+	radeon->vtbl.emit_query_begin = NULL;
 	if (radeon->radeonScreen->chip_family == CHIP_FAMILY_RV530) {
 		if (radeon->radeonScreen->num_z_pipes == 2)
 			radeon->vtbl.emit_query_finish = rv530_emit_query_finish_double_z;
diff --git a/src/mesa/drivers/dri/r600/r600_context.c b/src/mesa/drivers/dri/r600/r600_context.c
index 9776a86..1ed33ad 100644
--- a/src/mesa/drivers/dri/r600/r600_context.c
+++ b/src/mesa/drivers/dri/r600/r600_context.c
@@ -64,6 +64,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "r600_cmdbuf.h"
 #include "r600_emit.h"
 #include "radeon_bocs_wrapper.h"
+#include "radeon_queryobj.h"
 
 #include "r700_state.h"
 #include "r700_ioctl.h"
@@ -78,6 +79,7 @@ int future_hw_tcl_on = 1;
 int hw_tcl_on = 1;
 
 #define need_GL_VERSION_2_0
+#define need_GL_ARB_occlusion_query
 #define need_GL_ARB_point_parameters
 #define need_GL_ARB_vertex_program
 #define need_GL_EXT_blend_equation_separate
@@ -100,6 +102,7 @@ const struct dri_extension card_extensions[] = {
   /* *INDENT-OFF* */
   {"GL_ARB_depth_texture",		NULL},
   {"GL_ARB_fragment_program",		NULL},
+  {"GL_ARB_occlusion_query",		GL_ARB_occlusion_query_functions},
   {"GL_ARB_multitexture",		NULL},
   {"GL_ARB_point_parameters",		GL_ARB_point_parameters_functions},
   {"GL_ARB_shadow",			NULL},
@@ -203,6 +206,42 @@ static void r600_fallback(GLcontext *ctx, GLuint bit, GLboolean mode)
 		context->radeon.Fallback &= ~bit;
 }
 
+static void r600_emit_query_begin(radeonContextPtr radeon)
+{
+
+	//the gpu writes the zpass counter as one uint64_t to the specified location
+	//we store the start and end values of this counter in the first 16 bytes of the bo -> TODO: store multiple oq's in one bo (4096 bytes)
+	context_t *context = (context_t*) radeon;
+	BATCH_LOCALS(&context->radeon);
+
+	struct radeon_query_object *query = radeon->query.current;
+
+	//clearing zpass count disable bit not needed, because it should be cleared always
+	BEGIN_BATCH_NO_AUTOSTATE(4 + 2);
+	R600_OUT_BATCH(CP_PACKET3(R600_IT_EVENT_WRITE, 2));
+	R600_OUT_BATCH(ZPASS_DONE);
+	R600_OUT_BATCH(0x00000000); //gpu shall write at offset 0 of bo
+	R600_OUT_BATCH(0x00000000);
+	R600_OUT_BATCH_RELOC(VGT_EVENT_INITIATOR, query->bo, 0, 0, RADEON_GEM_DOMAIN_GTT, 0);
+	END_BATCH();
+}
+
+static void r600_emit_query_finish(radeonContextPtr radeon)
+{
+	context_t *context = (context_t*) radeon;
+	BATCH_LOCALS(&context->radeon);
+
+	struct radeon_query_object *query = radeon->query.current;
+
+	BEGIN_BATCH_NO_AUTOSTATE(4 + 2);
+	R600_OUT_BATCH(CP_PACKET3(R600_IT_EVENT_WRITE, 2));
+	R600_OUT_BATCH(ZPASS_DONE);
+	R600_OUT_BATCH(0x00000008); //0 + sizeof(uint64_t)
+	R600_OUT_BATCH(0x00000000);
+	R600_OUT_BATCH_RELOC(VGT_EVENT_INITIATOR, query->bo, 0, 0, RADEON_GEM_DOMAIN_GTT, 0);
+	END_BATCH();
+}
+
 static void r600_init_vtbl(radeonContextPtr radeon)
 {
 	radeon->vtbl.get_lock = r600_get_lock;
@@ -211,6 +250,8 @@ static void r600_init_vtbl(radeonContextPtr radeon)
 	radeon->vtbl.swtcl_flush = NULL;
 	radeon->vtbl.pre_emit_atoms = r600_vtbl_pre_emit_atoms;
 	radeon->vtbl.fallback = r600_fallback;
+	radeon->vtbl.emit_query_begin = r600_emit_query_begin;
+	radeon->vtbl.emit_query_finish = r600_emit_query_finish;
 }
 
 static void r600InitConstValues(GLcontext *ctx, radeonScreenPtr screen)
@@ -339,6 +380,7 @@ GLboolean r600CreateContext(const __GLcontextModes * glVisual,
 	r700InitStateFuncs(&functions);
 	r600InitTextureFuncs(&functions);
 	r700InitShaderFuncs(&functions);
+	radeonInitQueryObjFunctions(&functions);
 	r700InitIoctlFuncs(&functions);
 	radeonInitBufferObjectFuncs(&functions);
 
diff --git a/src/mesa/drivers/dri/r600/r700_state.c b/src/mesa/drivers/dri/r600/r700_state.c
index 3d3c8b9..8912996 100644
--- a/src/mesa/drivers/dri/r600/r700_state.c
+++ b/src/mesa/drivers/dri/r600/r700_state.c
@@ -1711,6 +1711,7 @@ void r700InitState(GLcontext * ctx) //-------------------
     SETfield(r700->DB_RENDER_OVERRIDE.u32All, FORCE_DISABLE, FORCE_HIZ_ENABLE_shift, FORCE_HIZ_ENABLE_mask);
     SETfield(r700->DB_RENDER_OVERRIDE.u32All, FORCE_DISABLE, FORCE_HIS_ENABLE0_shift, FORCE_HIS_ENABLE0_mask);
     SETfield(r700->DB_RENDER_OVERRIDE.u32All, FORCE_DISABLE, FORCE_HIS_ENABLE1_shift, FORCE_HIS_ENABLE1_mask);
+    SETbit(r700->DB_RENDER_OVERRIDE.u32All, NOOP_CULL_DISABLE_bit);
 
     r700->DB_ALPHA_TO_MASK.u32All = 0;
     SETfield(r700->DB_ALPHA_TO_MASK.u32All, 2, ALPHA_TO_MASK_OFFSET0_shift, ALPHA_TO_MASK_OFFSET0_mask);
diff --git a/src/mesa/drivers/dri/radeon/radeon_common_context.h b/src/mesa/drivers/dri/radeon/radeon_common_context.h
index 0309345..cf8463a 100644
--- a/src/mesa/drivers/dri/radeon/radeon_common_context.h
+++ b/src/mesa/drivers/dri/radeon/radeon_common_context.h
@@ -515,6 +515,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_begin)(radeonContextPtr radeon);
 	   void (*emit_query_finish)(radeonContextPtr radeon);
 	   void (*update_scissor)(GLcontext *ctx);
    } vtbl;
diff --git a/src/mesa/drivers/dri/radeon/radeon_queryobj.c b/src/mesa/drivers/dri/radeon/radeon_queryobj.c
index b79d864..37969c0 100644
--- a/src/mesa/drivers/dri/radeon/radeon_queryobj.c
+++ b/src/mesa/drivers/dri/radeon/radeon_queryobj.c
@@ -47,6 +47,8 @@ static int radeonQueryIsFlushed(GLcontext *ctx, struct gl_query_object *q)
 
 static void radeonQueryGetResult(GLcontext *ctx, struct gl_query_object *q)
 {
+	radeonContextPtr radeon = RADEON_CONTEXT(ctx);
+
 	struct radeon_query_object *query = (struct radeon_query_object *)q;
 	uint32_t *result;
 	int i;
@@ -59,10 +61,18 @@ static void radeonQueryGetResult(GLcontext *ctx, struct gl_query_object *q)
 
 	result = query->bo->ptr;
 
-	query->Base.Result = 0;
-	for (i = 0; i < query->curr_offset/sizeof(uint32_t); ++i) {
+	if (IS_R600_CLASS(radeon->radeonScreen))
+	{
+		uint64_t start_count = ((uint64_t*)result)[0];
+		uint64_t end_count = ((uint64_t*)result)[1];
+		query->Base.Result = end_count - start_count;
+	}
+	else{
+		query->Base.Result = 0;
+		for (i = 0; i < query->curr_offset/sizeof(uint32_t); ++i) {
 		query->Base.Result += result[i];
 		radeon_print(RADEON_STATE, RADEON_TRACE, "result[%d] = %d\n", i, result[i]);
+		}
 	}
 
 	radeon_bo_unmap(query->bo);
@@ -132,6 +142,14 @@ static void radeonBeginQuery(GLcontext *ctx, struct gl_query_object *q)
 
 	radeon->query.current = query;
 
+	if(radeon->vtbl.emit_query_begin) //r6/700
+	{
+		radeon_cs_space_check_with_bo(radeon->cmdbuf.cs,
+				      query->bo,
+				      0, RADEON_GEM_DOMAIN_GTT);
+		radeon->vtbl.emit_query_begin(radeon);
+	}
+
 	radeon->query.queryobj.dirty = GL_TRUE;
 	radeon->hw.is_dirty = GL_TRUE;
 	insert_at_tail(&radeon->query.not_flushed_head, query);
@@ -146,7 +164,8 @@ void radeonEmitQueryEnd(GLcontext *ctx)
 	if (!query)
 		return;
 
-	if (query->emitted_begin == GL_FALSE)
+	if ((query->emitted_begin == GL_FALSE) && (!IS_R600_CLASS(radeon->radeonScreen)))
+	//don't know what this check is good for on r300 (emitted_begin is never set)
 		return;
 
 	radeon_print(RADEON_STATE, RADEON_NORMAL, "%s: query id %d, bo %p, offset %d\n", __FUNCTION__, query->Base.Id, query->bo, query->curr_offset);
