radeon: add support for new dri2 interfaces & fix single buffer rendering
[mesa.git] / src / mesa / drivers / dri / radeon / radeon_common.c
index 2449795ea940efd5cdd4937d43fac08bf4c5b822..decea4518e6c50f5b3f6facefc40215d899e831c 100644 (file)
@@ -62,6 +62,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "main/bufferobj.h"
 #include "main/buffers.h"
 #include "main/depth.h"
+#include "main/polygon.h"
 #include "main/shaders.h"
 #include "main/texstate.h"
 #include "main/varray.h"
@@ -677,6 +678,7 @@ void radeon_draw_buffer(GLcontext *ctx, struct gl_framebuffer *fb)
                if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) {
                        rrbColor = radeon_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
                        radeon->front_cliprects = GL_TRUE;
+                       radeon->front_buffer_dirty = GL_TRUE;
                } else {
                        rrbColor = radeon_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
                        radeon->front_cliprects = GL_FALSE;
@@ -792,6 +794,24 @@ void radeonDrawBuffer( GLcontext *ctx, GLenum mode )
        if (RADEON_DEBUG & DEBUG_DRI)
                fprintf(stderr, "%s %s\n", __FUNCTION__,
                        _mesa_lookup_enum_by_nr( mode ));
+
+       if (ctx->DrawBuffer->Name == 0) {
+               radeonContextPtr radeon = RADEON_CONTEXT(ctx);
+
+               const GLboolean was_front_buffer_rendering =
+                       radeon->is_front_buffer_rendering;
+
+               radeon->is_front_buffer_rendering = (mode == GL_FRONT_LEFT) ||
+                                            (mode == GL_FRONT);
+
+      /* If we weren't front-buffer rendering before but we are now, make sure
+       * that the front-buffer has actually been allocated.
+       */
+               if (!was_front_buffer_rendering && radeon->is_front_buffer_rendering) {
+                       radeon_update_renderbuffers(radeon->dri.context,
+                               radeon->dri.context->driDrawablePriv);
+      }
+       }
        
        radeon_draw_buffer(ctx, ctx->DrawBuffer);
 }
@@ -851,20 +871,57 @@ void radeon_viewport(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei he
        radeon_window_moved(radeon);
        radeon_draw_buffer(ctx, radeon->glCtx->DrawBuffer);
        ctx->Driver.Viewport = old_viewport;
-
-
 }
-static void radeon_print_state_atom(radeonContextPtr radeon, struct radeon_state_atom *state )
-{
-       int i;
-       int dwords = (*state->check)(radeon->glCtx, state);
 
-       fprintf(stderr, "emit %s %d/%d\n", state->name, state->cmd_size, dwords);
-
-       if (RADEON_DEBUG & DEBUG_VERBOSE) 
-               for (i = 0 ; i < dwords; i++) 
-                       fprintf(stderr, "\t%s[%d]: %x\n", state->name, i, state->cmd[i]);
+static void radeon_print_state_atom(radeonContextPtr radeon, struct radeon_state_atom *state)
+{
+       int i, j, reg;
+       int dwords = (*state->check) (radeon->glCtx, state);
+       drm_r300_cmd_header_t cmd;
+
+       fprintf(stderr, "  emit %s %d/%d\n", state->name, dwords, state->cmd_size);
+
+       if (RADEON_DEBUG & DEBUG_VERBOSE) {
+               for (i = 0; i < dwords;) {
+                       cmd = *((drm_r300_cmd_header_t *) &state->cmd[i]);
+                       reg = (cmd.packet0.reghi << 8) | cmd.packet0.reglo;
+                       fprintf(stderr, "      %s[%d]: cmdpacket0 (first reg=0x%04x, count=%d)\n",
+                                       state->name, i, reg, cmd.packet0.count);
+                       ++i;
+                       for (j = 0; j < cmd.packet0.count && i < dwords; j++) {
+                               fprintf(stderr, "      %s[%d]: 0x%04x = %08x\n",
+                                               state->name, i, reg, state->cmd[i]);
+                               reg += 4;
+                               ++i;
+                       }
+               }
+       }
+}
 
+static void radeon_print_state_atom_kmm(radeonContextPtr radeon, struct radeon_state_atom *state)
+{
+       int i, j, reg, count;
+       int dwords = (*state->check) (radeon->glCtx, state);
+       uint32_t packet0;
+
+       fprintf(stderr, "  emit %s %d/%d\n", state->name, dwords, state->cmd_size);
+
+       if (RADEON_DEBUG & DEBUG_VERBOSE) {
+               for (i = 0; i < dwords;) {
+                       packet0 = state->cmd[i];
+                       reg = (packet0 & 0x1FFF) << 2;
+                       count = ((packet0 & 0x3FFF0000) >> 16) + 1;
+                       fprintf(stderr, "      %s[%d]: cmdpacket0 (first reg=0x%04x, count=%d)\n",
+                                       state->name, i, reg, count);
+                       ++i;
+                       for (j = 0; j < count && i < dwords; j++) {
+                               fprintf(stderr, "      %s[%d]: 0x%04x = %08x\n",
+                                               state->name, i, reg, state->cmd[i]);
+                               reg += 4;
+                               ++i;
+                       }
+               }
+       }
 }
 
 static INLINE void radeonEmitAtoms(radeonContextPtr radeon, GLboolean dirty)
@@ -882,7 +939,10 @@ static INLINE void radeonEmitAtoms(radeonContextPtr radeon, GLboolean dirty)
                        dwords = (*atom->check) (radeon->glCtx, atom);
                        if (dwords) {
                                if (DEBUG_CMDBUF && RADEON_DEBUG & DEBUG_STATE) {
-                                       radeon_print_state_atom(radeon, atom);
+                                       if (radeon->radeonScreen->kernel_mm)
+                                               radeon_print_state_atom_kmm(radeon, atom);
+                                       else
+                                               radeon_print_state_atom(radeon, atom);
                                }
                                if (atom->emit) {
                                        (*atom->emit)(radeon->glCtx, atom);
@@ -1005,6 +1065,26 @@ void radeonFlush(GLcontext *ctx)
    
        if (radeon->cmdbuf.cs->cdw)
                rcommonFlushCmdBuf(radeon, __FUNCTION__);
+
+       if ((ctx->DrawBuffer->Name == 0) && radeon->front_buffer_dirty) {
+               __DRIscreen *const screen = radeon->radeonScreen->driScreen;
+
+               if (screen->dri2.loader && (screen->dri2.loader->base.version >= 2)
+                       && (screen->dri2.loader->flushFrontBuffer != NULL)) {
+                       (*screen->dri2.loader->flushFrontBuffer)(radeon->dri.drawable,
+                                                 radeon->dri.drawable->loaderPrivate);
+
+                       /* Only clear the dirty bit if front-buffer rendering is no longer
+                        * enabled.  This is done so that the dirty bit can only be set in
+                        * glDrawBuffer.  Otherwise the dirty bit would have to be set at
+                        * each of N places that do rendering.  This has worse performances,
+                        * but it is much easier to get correct.
+                        */
+                       if (radeon->is_front_buffer_rendering) {
+                               radeon->front_buffer_dirty = GL_FALSE;
+                       }
+               }
+       }
 }
 
 /* Make sure all commands have been sent to the hardware and have
@@ -1146,7 +1226,7 @@ void rcommonInitCmdBuf(radeonContextPtr rmesa)
                radeon_cs_set_limit(rmesa->cmdbuf.cs, RADEON_GEM_DOMAIN_VRAM, rmesa->radeonScreen->texSize[0]);
                radeon_cs_set_limit(rmesa->cmdbuf.cs, RADEON_GEM_DOMAIN_GTT, rmesa->radeonScreen->gartTextures.size);
        } else {
-               struct drm_radeon_gem_info mminfo;
+               struct drm_radeon_gem_info mminfo = { 0 };
 
                if (!drmCommandWriteRead(rmesa->dri.fd, DRM_RADEON_GEM_INFO, &mminfo, sizeof(mminfo)))
                {
@@ -1258,6 +1338,7 @@ void radeon_clear_tris(GLcontext *ctx, GLbitfield mask)
                    GL_CURRENT_BIT |
                    GL_DEPTH_BUFFER_BIT |
                    GL_ENABLE_BIT |
+                   GL_POLYGON_BIT |
                    GL_STENCIL_BUFFER_BIT |
                    GL_TRANSFORM_BIT |
                    GL_CURRENT_BIT);
@@ -1279,6 +1360,7 @@ void radeon_clear_tris(GLcontext *ctx, GLbitfield mask)
    _mesa_Disable(GL_CLIP_PLANE3);
    _mesa_Disable(GL_CLIP_PLANE4);
    _mesa_Disable(GL_CLIP_PLANE5);
+   _mesa_PolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    if (ctx->Extensions.ARB_fragment_program && ctx->FragmentProgram.Enabled) {
       saved_fp_enable = GL_TRUE;
       _mesa_Disable(GL_FRAGMENT_PROGRAM_ARB);
@@ -1311,6 +1393,11 @@ void radeon_clear_tris(GLcontext *ctx, GLbitfield mask)
       }
    }
   
+#if FEATURE_ARB_vertex_buffer_object
+   _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+   _mesa_BindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+#endif
+
    radeon_meta_set_passthrough_transform(rmesa);
    
    for (i = 0; i < 4; i++) {
@@ -1382,7 +1469,7 @@ void radeon_clear_tris(GLcontext *ctx, GLbitfield mask)
       if (this_mask & BUFFER_BIT_STENCIL) {
         _mesa_Enable(GL_STENCIL_TEST);
         _mesa_StencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
-        _mesa_StencilFuncSeparate(GL_FRONT, GL_ALWAYS, ctx->Stencil.Clear,
+        _mesa_StencilFuncSeparate(GL_FRONT_AND_BACK, GL_ALWAYS, ctx->Stencil.Clear,
                                   ctx->Stencil.WriteMask[0]);
       } else {
         _mesa_Disable(GL_STENCIL_TEST);