gallium: pass the current context to the flush_front state tracker function
[mesa.git] / src / mesa / state_tracker / st_cb_drawpixels.c
index 5229ccee688a05f081e9fdf83c36a00b3a8faa4a..ff8a9dc43642446ca5e2a346d72b489823d3d23b 100644 (file)
@@ -43,6 +43,7 @@
 #include "main/texformat.h"
 #include "main/teximage.h"
 #include "main/texstore.h"
+#include "main/glformats.h"
 #include "program/program.h"
 #include "program/prog_print.h"
 #include "program/prog_instruction.h"
@@ -70,8 +71,6 @@
 #include "cso_cache/cso_context.h"
 
 
-#if FEATURE_drawpix
-
 /**
  * Check if the given program is:
  * 0: MOVE result.color, fragment.color;
@@ -217,7 +216,7 @@ st_make_drawpix_z_stencil_program(struct st_context *st,
    if (!p)
       return NULL;
 
-   p->NumInstructions = write_depth ? 2 : 1;
+   p->NumInstructions = write_depth ? 3 : 1;
    p->NumInstructions += write_stencil ? 1 : 0;
 
    p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
@@ -238,6 +237,13 @@ st_make_drawpix_z_stencil_program(struct st_context *st,
       p->Instructions[ic].TexSrcUnit = 0;
       p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
       ic++;
+      /* MOV result.color, fragment.color; */
+      p->Instructions[ic].Opcode = OPCODE_MOV;
+      p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
+      p->Instructions[ic].DstReg.Index = FRAG_RESULT_COLOR;
+      p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
+      p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_COL0;
+      ic++;
    }
 
    if (write_stencil) {
@@ -260,8 +266,10 @@ st_make_drawpix_z_stencil_program(struct st_context *st,
 
    p->InputsRead = FRAG_BIT_TEX0 | FRAG_BIT_COL0;
    p->OutputsWritten = 0;
-   if (write_depth)
+   if (write_depth) {
       p->OutputsWritten |= BITFIELD64_BIT(FRAG_RESULT_DEPTH);
+      p->OutputsWritten |= BITFIELD64_BIT(FRAG_RESULT_COLOR);
+   }
    if (write_stencil)
       p->OutputsWritten |= BITFIELD64_BIT(FRAG_RESULT_STENCIL);
 
@@ -359,7 +367,7 @@ internal_format(struct gl_context *ctx, GLenum format, GLenum type)
       return GL_STENCIL_INDEX;
 
    default:
-      if (_mesa_is_integer_format(format)) {
+      if (_mesa_is_enum_format_integer(format)) {
          switch (type) {
          case GL_BYTE:
             return GL_RGBA8I;
@@ -388,12 +396,16 @@ internal_format(struct gl_context *ctx, GLenum format, GLenum type)
 
          case GL_UNSIGNED_BYTE_3_3_2:
          case GL_UNSIGNED_BYTE_2_3_3_REV:
+            return GL_R3_G3_B2;
+
          case GL_UNSIGNED_SHORT_4_4_4_4:
          case GL_UNSIGNED_SHORT_4_4_4_4_REV:
             return GL_RGBA4;
 
          case GL_UNSIGNED_SHORT_5_6_5:
          case GL_UNSIGNED_SHORT_5_6_5_REV:
+            return GL_RGB565;
+
          case GL_UNSIGNED_SHORT_5_5_5_1:
          case GL_UNSIGNED_SHORT_1_5_5_5_REV:
             return GL_RGB5_A1;
@@ -504,12 +516,10 @@ make_texture(struct st_context *st,
       /* we'll do pixel transfer in a fragment shader */
       ctx->_ImageTransferState = 0x0;
 
-      transfer = pipe_get_transfer(st->pipe, pt, 0, 0,
-                                   PIPE_TRANSFER_WRITE, 0, 0,
-                                   width, height);
-
       /* map texture transfer */
-      dest = pipe_transfer_map(pipe, transfer);
+      dest = pipe_transfer_map(pipe, pt, 0, 0,
+                               PIPE_TRANSFER_WRITE, 0, 0,
+                               width, height, &transfer);
 
 
       /* Put image into texture transfer.
@@ -528,7 +538,6 @@ make_texture(struct st_context *st,
 
       /* unmap */
       pipe_transfer_unmap(pipe, transfer);
-      pipe->transfer_destroy(pipe, transfer);
 
       assert(success);
 
@@ -555,7 +564,15 @@ draw_quad(struct gl_context *ctx, GLfloat x0, GLfloat y0, GLfloat z,
 {
    struct st_context *st = st_context(ctx);
    struct pipe_context *pipe = st->pipe;
-   GLfloat verts[4][3][4]; /* four verts, three attribs, XYZW */
+   GLfloat (*verts)[3][4]; /* four verts, three attribs, XYZW */
+   struct pipe_resource *buf = NULL;
+   unsigned offset;
+
+   u_upload_alloc(st->uploader, 0, 4 * sizeof(verts[0]), &offset, &buf,
+                 (void**)&verts);
+   if (!buf) {
+      return;
+   }
 
    /* setup vertex data */
    {
@@ -619,22 +636,14 @@ draw_quad(struct gl_context *ctx, GLfloat x0, GLfloat y0, GLfloat z,
       }
    }
 
-   {
-      struct pipe_resource *buf = NULL;
-      unsigned offset;
-
-      u_upload_data(st->uploader, 0, sizeof(verts), verts, &offset, &buf);
-      if (!buf) {
-         return;
-      }
-
-      u_upload_unmap(st->uploader);
-      util_draw_vertex_buffer(pipe, st->cso_context, buf, offset,
-                              PIPE_PRIM_QUADS,
-                              4,  /* verts */
-                              3); /* attribs/vert */
-      pipe_resource_reference(&buf, NULL);
-   }
+   u_upload_unmap(st->uploader);
+   util_draw_vertex_buffer(pipe, st->cso_context, buf,
+                           cso_get_aux_vertex_buffer_slot(st->cso_context),
+                           offset,
+                          PIPE_PRIM_QUADS,
+                          4,  /* verts */
+                          3); /* attribs/vert */
+   pipe_resource_reference(&buf, NULL);
 }
 
 
@@ -669,14 +678,14 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
 
    cso_save_rasterizer(cso);
    cso_save_viewport(cso);
-   cso_save_samplers(cso);
-   cso_save_fragment_sampler_views(cso);
+   cso_save_samplers(cso, PIPE_SHADER_FRAGMENT);
+   cso_save_sampler_views(cso, PIPE_SHADER_FRAGMENT);
    cso_save_fragment_shader(cso);
    cso_save_stream_outputs(cso);
    cso_save_vertex_shader(cso);
    cso_save_geometry_shader(cso);
    cso_save_vertex_elements(cso);
-   cso_save_vertex_buffers(cso);
+   cso_save_aux_vertex_buffer_slot(cso);
    if (write_stencil) {
       cso_save_depth_stencil_alpha(cso);
       cso_save_blend(cso);
@@ -687,7 +696,8 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
       struct pipe_rasterizer_state rasterizer;
       memset(&rasterizer, 0, sizeof(rasterizer));
       rasterizer.clamp_fragment_color = !st->clamp_frag_color_in_shader &&
-                                        ctx->Color._ClampFragmentColor;
+                                        ctx->Color._ClampFragmentColor &&
+                                        !ctx->DrawBuffer->_IntegerColor;
       rasterizer.gl_rasterization_rules = 1;
       rasterizer.depth_clip = !ctx->Transform.DepthClamp;
       rasterizer.scissor = ctx->Scissor.Enabled;
@@ -741,11 +751,11 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
       sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
       sampler.normalized_coords = normalized;
 
-      cso_single_sampler(cso, 0, &sampler);
+      cso_single_sampler(cso, PIPE_SHADER_FRAGMENT, 0, &sampler);
       if (num_sampler_view > 1) {
-         cso_single_sampler(cso, 1, &sampler);
+         cso_single_sampler(cso, PIPE_SHADER_FRAGMENT, 1, &sampler);
       }
-      cso_single_sampler_done(cso);
+      cso_single_sampler_done(cso, PIPE_SHADER_FRAGMENT);
    }
 
    /* viewport state: viewport matching window dims */
@@ -768,7 +778,7 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
    cso_set_stream_outputs(st->cso_context, 0, NULL, 0);
 
    /* texture state: */
-   cso_set_fragment_sampler_views(cso, num_sampler_view, sv);
+   cso_set_sampler_views(cso, PIPE_SHADER_FRAGMENT, num_sampler_view, sv);
 
    /* Compute Gallium window coords (y=0=top) with pixel zoom.
     * Recall that these coords are transformed by the current
@@ -794,13 +804,13 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
    /* restore state */
    cso_restore_rasterizer(cso);
    cso_restore_viewport(cso);
-   cso_restore_samplers(cso);
-   cso_restore_fragment_sampler_views(cso);
+   cso_restore_samplers(cso, PIPE_SHADER_FRAGMENT);
+   cso_restore_sampler_views(cso, PIPE_SHADER_FRAGMENT);
    cso_restore_fragment_shader(cso);
    cso_restore_vertex_shader(cso);
    cso_restore_geometry_shader(cso);
    cso_restore_vertex_elements(cso);
-   cso_restore_vertex_buffers(cso);
+   cso_restore_aux_vertex_buffer_slot(cso);
    cso_restore_stream_outputs(cso);
    if (write_stencil) {
       cso_restore_depth_stencil_alpha(cso);
@@ -854,18 +864,16 @@ draw_stencil_pixels(struct gl_context *ctx, GLint x, GLint y,
       usage = PIPE_TRANSFER_WRITE;
    }
 
-   pt = pipe_get_transfer(pipe, strb->texture,
-                          strb->rtt_level, strb->rtt_face + strb->rtt_slice,
-                          usage, x, y,
-                          width, height);
-
-   stmap = pipe_transfer_map(pipe, pt);
+   stmap = pipe_transfer_map(pipe, strb->texture,
+                             strb->rtt_level, strb->rtt_face + strb->rtt_slice,
+                             usage, x, y,
+                             width, height, &pt);
 
    pixels = _mesa_map_pbo_source(ctx, &clippedUnpack, pixels);
    assert(pixels);
 
-   sValues = (GLubyte *) malloc(width * sizeof(GLubyte));
-   zValues = (GLuint *) malloc(width * sizeof(GLuint));
+   sValues = malloc(width * sizeof(GLubyte));
+   zValues = malloc(width * sizeof(GLuint));
 
    if (sValues && zValues) {
       GLint row;
@@ -987,7 +995,6 @@ draw_stencil_pixels(struct gl_context *ctx, GLint x, GLint y,
 
    /* unmap the stencil buffer */
    pipe_transfer_unmap(pipe, pt);
-   pipe->transfer_destroy(pipe, pt);
 }
 
 
@@ -1016,7 +1023,8 @@ get_color_fp_variant(struct st_context *st)
                        ctx->Pixel.AlphaScale != 1.0);
    key.pixelMaps = ctx->Pixel.MapColorFlag;
    key.clamp_color = st->clamp_frag_color_in_shader &&
-                     st->ctx->Color._ClampFragmentColor;
+                     st->ctx->Color._ClampFragmentColor &&
+                     !st->ctx->DrawBuffer->_IntegerColor;
 
    fpv = st_get_fp_variant(st, st->fp, &key);
 
@@ -1048,6 +1056,28 @@ get_depth_stencil_fp_variant(struct st_context *st, GLboolean write_depth,
 }
 
 
+/**
+ * Clamp glDrawPixels width and height to the maximum texture size.
+ */
+static void
+clamp_size(struct pipe_context *pipe, GLsizei *width, GLsizei *height,
+           struct gl_pixelstore_attrib *unpack)
+{
+   const unsigned maxSize = 
+      1 << (pipe->screen->get_param(pipe->screen,
+                                    PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
+
+   if (*width > maxSize) {
+      if (unpack->RowLength == 0)
+         unpack->RowLength = *width;
+      *width = maxSize;
+   }
+   if (*height > maxSize) {
+      *height = maxSize;
+   }
+}
+
+
 /**
  * Called via ctx->Driver.DrawPixels()
  */
@@ -1065,6 +1095,20 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
    struct pipe_sampler_view *sv[2];
    int num_sampler_view = 1;
    struct st_fp_variant *fpv;
+   struct gl_pixelstore_attrib clippedUnpack;
+
+   /* Mesa state should be up to date by now */
+   assert(ctx->NewState == 0x0);
+
+   st_validate_state(st);
+
+   /* Limit the size of the glDrawPixels to the max texture size.
+    * Strictly speaking, that's not correct but since we don't handle
+    * larger images yet, this is better than crashing.
+    */
+   clippedUnpack = *unpack;
+   unpack = &clippedUnpack;
+   clamp_size(st->pipe, &width, &height, &clippedUnpack);
 
    if (format == GL_DEPTH_STENCIL)
       write_stencil = write_depth = GL_TRUE;
@@ -1081,11 +1125,6 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
       return;
    }
 
-   /* Mesa state should be up to date by now */
-   assert(ctx->NewState == 0x0);
-
-   st_validate_state(st);
-
    /*
     * Get vertex/fragment shaders
     */
@@ -1127,27 +1166,8 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
              * The stencil is written using the shader stencil export
              * functionality. */
             if (write_stencil) {
-               enum pipe_format stencil_format = PIPE_FORMAT_NONE;
-
-               switch (pt->format) {
-               case PIPE_FORMAT_Z24_UNORM_S8_UINT:
-               case PIPE_FORMAT_X24S8_UINT:
-                  stencil_format = PIPE_FORMAT_X24S8_UINT;
-                  break;
-               case PIPE_FORMAT_S8_UINT_Z24_UNORM:
-               case PIPE_FORMAT_S8X24_UINT:
-                  stencil_format = PIPE_FORMAT_S8X24_UINT;
-                  break;
-               case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
-               case PIPE_FORMAT_X32_S8X24_UINT:
-                  stencil_format = PIPE_FORMAT_X32_S8X24_UINT;
-                  break;
-               case PIPE_FORMAT_S8_UINT:
-                  stencil_format = PIPE_FORMAT_S8_UINT;
-                  break;
-               default:
-                  assert(0);
-               }
+               enum pipe_format stencil_format =
+                     util_format_stencil_only(pt->format);
 
                sv[1] = st_create_texture_sampler_view_format(st->pipe, pt,
                                                              stencil_format);
@@ -1225,18 +1245,16 @@ copy_stencil_pixels(struct gl_context *ctx, GLint srcx, GLint srcy,
       dsty = rbDraw->Base.Height - dsty - height;
    }
 
-   ptDraw = pipe_get_transfer(pipe,
-                              rbDraw->texture,
-                              rbDraw->rtt_level,
-                              rbDraw->rtt_face + rbDraw->rtt_slice,
-                              usage, dstx, dsty,
-                              width, height);
-
-   assert(util_format_get_blockwidth(ptDraw->resource->format) == 1);
-   assert(util_format_get_blockheight(ptDraw->resource->format) == 1);
+   assert(util_format_get_blockwidth(rbDraw->texture->format) == 1);
+   assert(util_format_get_blockheight(rbDraw->texture->format) == 1);
 
    /* map the stencil buffer */
-   drawMap = pipe_transfer_map(pipe, ptDraw);
+   drawMap = pipe_transfer_map(pipe,
+                               rbDraw->texture,
+                               rbDraw->rtt_level,
+                               rbDraw->rtt_face + rbDraw->rtt_slice,
+                               usage, dstx, dsty,
+                               width, height, &ptDraw);
 
    /* draw */
    /* XXX PixelZoom not handled yet */
@@ -1261,7 +1279,6 @@ copy_stencil_pixels(struct gl_context *ctx, GLint srcx, GLint srcy,
 
    /* unmap the stencil buffer */
    pipe_transfer_unmap(pipe, ptDraw);
-   pipe->transfer_destroy(pipe, ptDraw);
 }
 
 
@@ -1511,7 +1528,15 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
    readY = srcy;
    readW = width;
    readH = height;
-   _mesa_clip_readpixels(ctx, &readX, &readY, &readW, &readH, &pack);
+   if (!_mesa_clip_readpixels(ctx, &readX, &readY, &readW, &readH, &pack)) {
+      /* The source region is completely out of bounds.  Do nothing.
+       * The GL spec says "Results of copies from outside the window,
+       * or from regions of the window that are not exposed, are
+       * hardware dependent and undefined."
+       */
+      return;
+   }
+
    readW = MAX2(0, readW);
    readH = MAX2(0, readH);
 
@@ -1543,13 +1568,15 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
    }
    else {
       /* CPU-based fallback/conversion */
-      struct pipe_transfer *ptRead =
-         pipe_get_transfer(st->pipe, rbRead->texture,
+      struct pipe_transfer *ptRead;
+      void *mapRead =
+         pipe_transfer_map(st->pipe, rbRead->texture,
                            rbRead->rtt_level,
                            rbRead->rtt_face + rbRead->rtt_slice,
                            PIPE_TRANSFER_READ,
-                           readX, readY, readW, readH);
+                           readX, readY, readW, readH, &ptRead);
       struct pipe_transfer *ptTex;
+      void *mapTex;
       enum pipe_transfer_usage transfer_usage;
 
       if (ST_DEBUG & DEBUG_FALLBACK)
@@ -1560,33 +1587,34 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
       else
          transfer_usage = PIPE_TRANSFER_WRITE;
 
-      ptTex = pipe_get_transfer(st->pipe, pt, 0, 0, transfer_usage,
-                                0, 0, width, height);
+      mapTex = pipe_transfer_map(st->pipe, pt, 0, 0, transfer_usage,
+                                 0, 0, width, height, &ptTex);
 
       /* copy image from ptRead surface to ptTex surface */
       if (type == GL_COLOR) {
          /* alternate path using get/put_tile() */
-         GLfloat *buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
+         GLfloat *buf = malloc(width * height * 4 * sizeof(GLfloat));
          enum pipe_format readFormat, drawFormat;
          readFormat = util_format_linear(rbRead->texture->format);
          drawFormat = util_format_linear(pt->format);
-         pipe_get_tile_rgba_format(pipe, ptRead, 0, 0, readW, readH,
+         pipe_get_tile_rgba_format(ptRead, mapRead, 0, 0, readW, readH,
                                    readFormat, buf);
-         pipe_put_tile_rgba_format(pipe, ptTex, pack.SkipPixels, pack.SkipRows,
+         pipe_put_tile_rgba_format(ptTex, mapTex, pack.SkipPixels,
+                                   pack.SkipRows,
                                    readW, readH, drawFormat, buf);
          free(buf);
       }
       else {
          /* GL_DEPTH */
-         GLuint *buf = (GLuint *) malloc(width * height * sizeof(GLuint));
-         pipe_get_tile_z(pipe, ptRead, 0, 0, readW, readH, buf);
-         pipe_put_tile_z(pipe, ptTex, pack.SkipPixels, pack.SkipRows,
+         GLuint *buf = malloc(width * height * sizeof(GLuint));
+         pipe_get_tile_z(ptRead, mapRead, 0, 0, readW, readH, buf);
+         pipe_put_tile_z(ptTex, mapTex, pack.SkipPixels, pack.SkipRows,
                          readW, readH, buf);
          free(buf);
       }
 
-      pipe->transfer_destroy(pipe, ptRead);
-      pipe->transfer_destroy(pipe, ptTex);
+      pipe->transfer_unmap(pipe, ptRead);
+      pipe->transfer_unmap(pipe, ptTex);
    }
 
    /* OK, the texture 'pt' contains the src image/pixels.  Now draw a
@@ -1629,5 +1657,3 @@ st_destroy_drawpix(struct st_context *st)
    if (st->drawpix.vert_shaders[1])
       cso_delete_vertex_shader(st->cso_context, st->drawpix.vert_shaders[1]);
 }
-
-#endif /* FEATURE_drawpix */