Introduce .editorconfig
[mesa.git] / src / mesa / drivers / dri / i915 / intel_pixel_read.c
index 2e31656e984080fe6a3a7c28caa0b9283ade9993..e6fa8f2dce8e7ad95c5ae908340a3d99ffce9666 100644 (file)
@@ -1,8 +1,8 @@
 /**************************************************************************
- * 
- * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ *
+ * Copyright 2003 VMware, Inc.
  * All Rights Reserved.
- * 
+ *
  * 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
  * distribute, sub license, 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 NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS 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.
- * 
+ *
  **************************************************************************/
 
-#include "glheader.h"
-#include "enums.h"
-#include "mtypes.h"
-#include "macros.h"
-#include "image.h"
-#include "bufferobj.h"
-#include "swrast/swrast.h"
+#include "main/glheader.h"
+#include "main/enums.h"
+#include "main/mtypes.h"
+#include "main/macros.h"
+#include "main/fbobject.h"
+#include "main/image.h"
+#include "main/bufferobj.h"
+#include "main/readpix.h"
+#include "main/state.h"
 
 #include "intel_screen.h"
 #include "intel_context.h"
-#include "intel_ioctl.h"
-#include "intel_batchbuffer.h"
 #include "intel_blit.h"
 #include "intel_buffers.h"
+#include "intel_fbo.h"
+#include "intel_mipmap_tree.h"
 #include "intel_regions.h"
 #include "intel_pixel.h"
 #include "intel_buffer_objects.h"
 
+#define FILE_DEBUG_FLAG DEBUG_PIXEL
+
 /* For many applications, the new ability to pull the source buffers
  * back out of the GTT and then do the packing/conversion operations
  * in software will be as much of an improvement as trying to get the
- * blitter and/or texture engine to do the work. 
+ * blitter and/or texture engine to do the work.
  *
  * This step is gated on private backbuffers.
- * 
+ *
  * Obviously the frontbuffer can't be pulled back, so that is either
  * an argument for blit/texture readpixels, or for blitting to a
  * temporary and then pulling that back.
  * any case.
  */
 
-
-static GLboolean
-do_texture_readpixels(GLcontext * ctx,
-                      GLint x, GLint y, GLsizei width, GLsizei height,
-                      GLenum format, GLenum type,
-                      const struct gl_pixelstore_attrib *pack,
-                      struct intel_region *dest_region)
-{
-#if 0
-   struct intel_context *intel = intel_context(ctx);
-   intelScreenPrivate *screen = intel->intelScreen;
-   GLint pitch = pack->RowLength ? pack->RowLength : width;
-   __DRIdrawablePrivate *dPriv = intel->driDrawable;
-   int textureFormat;
-   GLenum glTextureFormat;
-   int destFormat, depthFormat, destPitch;
-   drm_clip_rect_t tmp;
-
-   if (INTEL_DEBUG & DEBUG_PIXEL)
-      fprintf(stderr, "%s\n", __FUNCTION__);
-
-
-   if (ctx->_ImageTransferState ||
-       pack->SwapBytes || pack->LsbFirst || !pack->Invert) {
-      if (INTEL_DEBUG & DEBUG_PIXEL)
-         fprintf(stderr, "%s: check_color failed\n", __FUNCTION__);
-      return GL_FALSE;
-   }
-
-   intel->vtbl.meta_texrect_source(intel, intel_readbuf_region(intel));
-
-   if (!intel->vtbl.meta_render_dest(intel, dest_region, type, format)) {
-      if (INTEL_DEBUG & DEBUG_PIXEL)
-         fprintf(stderr, "%s: couldn't set dest %s/%s\n",
-                 __FUNCTION__,
-                 _mesa_lookup_enum_by_nr(type),
-                 _mesa_lookup_enum_by_nr(format));
-      return GL_FALSE;
-   }
-
-   LOCK_HARDWARE(intel);
-
-   if (intel->driDrawable->numClipRects) {
-      intel->vtbl.install_meta_state(intel);
-      intel->vtbl.meta_no_depth_write(intel);
-      intel->vtbl.meta_no_stencil_write(intel);
-
-      if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) {
-         UNLOCK_HARDWARE(intel);
-         SET_STATE(i830, state);
-         if (INTEL_DEBUG & DEBUG_PIXEL)
-            fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__);
-         return GL_TRUE;
-      }
-
-      y = dPriv->h - y - height;
-      x += dPriv->x;
-      y += dPriv->y;
-
-
-      /* Set the frontbuffer up as a large rectangular texture.
-       */
-      intel->vtbl.meta_tex_rect_source(intel, src_region, textureFormat);
-
-
-      intel->vtbl.meta_texture_blend_replace(i830, glTextureFormat);
-
-
-      /* Set the 3d engine to draw into the destination region:
-       */
-
-      intel->vtbl.meta_draw_region(intel, dest_region);
-      intel->vtbl.meta_draw_format(intel, destFormat, depthFormat);     /* ?? */
-
-
-      /* Draw a single quad, no cliprects:
-       */
-      intel->vtbl.meta_disable_cliprects(intel);
-
-      intel->vtbl.draw_quad(intel,
-                            0, width, 0, height,
-                            0x00ff00ff, x, x + width, y, y + height);
-
-      intel->vtbl.leave_meta_state(intel);
-   }
-   UNLOCK_HARDWARE(intel);
-
-   intel_region_wait_fence(ctx, dest_region);   /* required by GL */
-   return GL_TRUE;
-#endif
-
-   return GL_FALSE;
-}
-
-
-
-
-static GLboolean
-do_blit_readpixels(GLcontext * ctx,
+static bool
+do_blit_readpixels(struct gl_context * ctx,
                    GLint x, GLint y, GLsizei width, GLsizei height,
                    GLenum format, GLenum type,
                    const struct gl_pixelstore_attrib *pack, GLvoid * pixels)
 {
    struct intel_context *intel = intel_context(ctx);
-   struct intel_region *src = intel_readbuf_region(intel);
    struct intel_buffer_object *dst = intel_buffer_object(pack->BufferObj);
    GLuint dst_offset;
-   GLuint rowLength;
-   dri_fence *fence = NULL;
+   drm_intel_bo *dst_buffer;
+   GLint dst_x, dst_y;
+   GLuint dirty;
 
-   if (INTEL_DEBUG & DEBUG_PIXEL)
-      _mesa_printf("%s\n", __FUNCTION__);
+   DBG("%s\n", __func__);
 
-   if (!src)
-      return GL_FALSE;
-
-   if (dst) {
-      /* XXX This validation should be done by core mesa:
-       */
-      if (!_mesa_validate_pbo_access(2, pack, width, height, 1,
-                                     format, type, pixels)) {
-         _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels");
-         return GL_TRUE;
-      }
-   }
-   else {
-      /* PBO only for now:
-       */
-      if (INTEL_DEBUG & DEBUG_PIXEL)
-         _mesa_printf("%s - not PBO\n", __FUNCTION__);
-      return GL_FALSE;
-   }
+   assert(_mesa_is_bufferobj(pack->BufferObj));
 
+   struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
+   struct intel_renderbuffer *irb = intel_renderbuffer(rb);
 
    if (ctx->_ImageTransferState ||
-       !intel_check_blit_format(src, format, type)) {
-      if (INTEL_DEBUG & DEBUG_PIXEL)
-         _mesa_printf("%s - bad format for blit\n", __FUNCTION__);
-      return GL_FALSE;
+       !_mesa_format_matches_format_and_type(irb->mt->format, format, type,
+                                             false, NULL)) {
+      DBG("%s - bad format for blit\n", __func__);
+      return false;
    }
 
-   if (pack->Alignment != 1 || pack->SwapBytes || pack->LsbFirst) {
-      if (INTEL_DEBUG & DEBUG_PIXEL)
-         _mesa_printf("%s: bad packing params\n", __FUNCTION__);
-      return GL_FALSE;
+   if (pack->SwapBytes || pack->LsbFirst) {
+      DBG("%s: bad packing params\n", __func__);
+      return false;
    }
 
-   if (pack->RowLength > 0)
-      rowLength = pack->RowLength;
-   else
-      rowLength = width;
-
+   int dst_stride = _mesa_image_row_stride(pack, width, format, type);
+   bool dst_flip = false;
+   /* Mesa flips the dst_stride for pack->Invert, but we want our mt to have a
+    * normal dst_stride.
+    */
    if (pack->Invert) {
-      if (INTEL_DEBUG & DEBUG_PIXEL)
-         _mesa_printf("%s: MESA_PACK_INVERT not done yet\n", __FUNCTION__);
-      return GL_FALSE;
-   }
-   else {
-      rowLength = -rowLength;
+      dst_stride = -dst_stride;
+      dst_flip = true;
    }
 
-   /* XXX 64-bit cast? */
-   dst_offset = (GLuint) _mesa_image_address(2, pack, pixels, width, height,
-                                             format, type, 0, 0, 0);
-
-
-   /* Although the blits go on the command buffer, need to do this and
-    * fire with lock held to guarentee cliprects are correct.
-    */
-   intelFlush(&intel->ctx);
-   LOCK_HARDWARE(intel);
-
-   if (intel->driDrawable->numClipRects) {
-      GLboolean all = (width * height * src->cpp == dst->Base.Size &&
-                       x == 0 && dst_offset == 0);
-
-      dri_bo *dst_buffer = intel_bufferobj_buffer(intel, dst,
-                                                 all ? INTEL_WRITE_FULL :
-                                                 INTEL_WRITE_PART);
-      __DRIdrawablePrivate *dPriv = intel->driDrawable;
-      int nbox = dPriv->numClipRects;
-      drm_clip_rect_t *box = dPriv->pClipRects;
-      drm_clip_rect_t rect;
-      drm_clip_rect_t src_rect;
-      int i;
-
-      src_rect.x1 = dPriv->x + x;
-      src_rect.y1 = dPriv->y + dPriv->h - (y + height);
-      src_rect.x2 = src_rect.x1 + width;
-      src_rect.y2 = src_rect.y1 + height;
-
-
-
-      for (i = 0; i < nbox; i++) {
-         if (!intel_intersect_cliprects(&rect, &src_rect, &box[i]))
-            continue;
-
-         intelEmitCopyBlit(intel,
-                           src->cpp,
-                           src->pitch, src->buffer, 0, src->tiled,
-                           rowLength, dst_buffer, dst_offset, GL_FALSE,
-                           rect.x1,
-                           rect.y1,
-                           rect.x1 - src_rect.x1,
-                           rect.y2 - src_rect.y2,
-                           rect.x2 - rect.x1, rect.y2 - rect.y1,
-                          GL_COPY);
-      }
-
-      intel_batchbuffer_flush(intel->batch);
-      fence = intel->batch->last_fence;
-      dri_fence_reference(fence);
+   dst_offset = (GLintptr)pixels;
+   dst_offset += _mesa_image_offset(2, pack, width, height,
+                                   format, type, 0, 0, 0);
 
+   if (!_mesa_clip_copytexsubimage(ctx,
+                                  &dst_x, &dst_y,
+                                  &x, &y,
+                                  &width, &height)) {
+      return true;
    }
-   UNLOCK_HARDWARE(intel);
 
-   if (fence) {
-      dri_fence_wait(fence);
-      dri_fence_unreference(fence);
+   dirty = intel->front_buffer_dirty;
+   intel_prepare_render(intel);
+   intel->front_buffer_dirty = dirty;
+
+   dst_buffer = intel_bufferobj_buffer(intel, dst);
+
+   struct intel_mipmap_tree *pbo_mt =
+      intel_miptree_create_for_bo(intel,
+                                  dst_buffer,
+                                  irb->mt->format,
+                                  dst_offset,
+                                  width, height,
+                                  dst_stride, I915_TILING_NONE);
+
+   if (!intel_miptree_blit(intel,
+                           irb->mt, irb->mt_level, irb->mt_layer,
+                           x, y, _mesa_is_winsys_fbo(ctx->ReadBuffer),
+                           pbo_mt, 0, 0,
+                           0, 0, dst_flip,
+                           width, height, GL_COPY)) {
+      intel_miptree_release(&pbo_mt);
+      return false;
    }
 
-   if (INTEL_DEBUG & DEBUG_PIXEL)
-      _mesa_printf("%s - DONE\n", __FUNCTION__);
+   intel_miptree_release(&pbo_mt);
+
+   DBG("%s - DONE\n", __func__);
 
-   return GL_TRUE;
+   return true;
 }
 
 void
-intelReadPixels(GLcontext * ctx,
+intelReadPixels(struct gl_context * ctx,
                 GLint x, GLint y, GLsizei width, GLsizei height,
                 GLenum format, GLenum type,
                 const struct gl_pixelstore_attrib *pack, GLvoid * pixels)
 {
-   if (INTEL_DEBUG & DEBUG_PIXEL)
-      fprintf(stderr, "%s\n", __FUNCTION__);
+   struct intel_context *intel = intel_context(ctx);
+   bool dirty;
+
+   intel_flush_rendering_to_batch(ctx);
+
+   DBG("%s\n", __func__);
+
+   if (_mesa_is_bufferobj(pack->BufferObj)) {
+      /* Using PBOs, so try the BLT based path. */
+      if (do_blit_readpixels(ctx, x, y, width, height, format, type, pack,
+                             pixels)) {
+         return;
+      }
+
+      perf_debug("%s: fallback to CPU mapping in PBO case\n", __func__);
+   }
 
-   intelFlush(ctx);
+   /* glReadPixels() wont dirty the front buffer, so reset the dirty
+    * flag after calling intel_prepare_render(). */
+   dirty = intel->front_buffer_dirty;
+   intel_prepare_render(intel);
+   intel->front_buffer_dirty = dirty;
 
-   if (do_blit_readpixels
-       (ctx, x, y, width, height, format, type, pack, pixels))
-      return;
+   /* Update Mesa state before calling _mesa_readpixels().
+    * XXX this may not be needed since ReadPixels no longer uses the
+    * span code.
+    */
 
-   if (do_texture_readpixels
-       (ctx, x, y, width, height, format, type, pack, pixels))
-      return;
+   if (ctx->NewState)
+      _mesa_update_state(ctx);
 
-   if (INTEL_DEBUG & DEBUG_PIXEL)
-      _mesa_printf("%s: fallback to swrast\n", __FUNCTION__);
+   _mesa_readpixels(ctx, x, y, width, height, format, type, pack, pixels);
 
-   _swrast_ReadPixels(ctx, x, y, width, height, format, type, pack, pixels);
+   /* There's an intel_prepare_render() call in intelSpanRenderStart(). */
+   intel->front_buffer_dirty = dirty;
 }