Esempio n. 1
0
static void
intel_flush_front(struct gl_context *ctx)
{
   struct intel_context *intel = intel_context(ctx);
    __DRIcontext *driContext = intel->driContext;
    __DRIdrawable *driDrawable = driContext->driDrawablePriv;
    __DRIscreen *const screen = intel->intelScreen->driScrnPriv;

    if (_mesa_is_winsys_fbo(ctx->DrawBuffer) && intel->front_buffer_dirty) {
      if (screen->dri2.loader->flushFrontBuffer != NULL &&
          driDrawable &&
          driDrawable->loaderPrivate) {

         /* Downsample before flushing FAKE_FRONT_LEFT to FRONT_LEFT.
          *
          * This potentially downsamples both front and back buffer. It
          * is unnecessary to downsample the back, but harms nothing except
          * performance. And no one cares about front-buffer render
          * performance.
          */
         intel_downsample_for_dri2_flush(intel, driDrawable);

         screen->dri2.loader->flushFrontBuffer(driDrawable,
                                               driDrawable->loaderPrivate);

	 /* We set the dirty bit in intel_prepare_render() if we're
	  * front buffer rendering once we get there.
	  */
	 intel->front_buffer_dirty = false;
      }
   }
}
Esempio n. 2
0
void GLAPIENTRY
_mesa_GetMultisamplefv(GLenum pname, GLuint index, GLfloat * val)
{
   GET_CURRENT_CONTEXT(ctx);

   if (ctx->NewState & _NEW_BUFFERS) {
      _mesa_update_state(ctx);
   }

   switch (pname) {
   case GL_SAMPLE_POSITION: {
      if ((int) index >= ctx->DrawBuffer->Visual.samples) {
         _mesa_error( ctx, GL_INVALID_VALUE, "glGetMultisamplefv(index)" );
         return;
      }

      ctx->Driver.GetSamplePosition(ctx, ctx->DrawBuffer, index, val);

      /* winsys FBOs are upside down */
      if (_mesa_is_winsys_fbo(ctx->DrawBuffer))
         val[1] = 1 - val[1];

      return;
   }

   default:
      _mesa_error( ctx, GL_INVALID_ENUM, "glGetMultisamplefv(pname)" );
      return;
   }
}
Esempio n. 3
0
static void
intel_flush_front(struct gl_context *ctx)
{
   struct brw_context *brw = brw_context(ctx);
   __DRIcontext *driContext = brw->driContext;
   __DRIdrawable *driDrawable = driContext->driDrawablePriv;
   __DRIscreen *const screen = brw->intelScreen->driScrnPriv;

   if (brw->front_buffer_dirty && _mesa_is_winsys_fbo(ctx->DrawBuffer)) {
      if (flushFront(screen) && driDrawable &&
          driDrawable->loaderPrivate) {

         /* Resolve before flushing FAKE_FRONT_LEFT to FRONT_LEFT.
          *
          * This potentially resolves both front and back buffer. It
          * is unnecessary to resolve the back, but harms nothing except
          * performance. And no one cares about front-buffer render
          * performance.
          */
         intel_resolve_for_dri2_flush(brw, driDrawable);
         intel_batchbuffer_flush(brw);

         flushFront(screen)(driDrawable, driDrawable->loaderPrivate);

         /* We set the dirty bit in intel_prepare_render() if we're
          * front buffer rendering once we get there.
          */
         brw->front_buffer_dirty = false;
      }
   }
}
Esempio n. 4
0
/**
 * Polygon stipple offset packet
 */
static void
upload_polygon_stipple_offset(struct brw_context *brw)
{
   struct gl_context *ctx = &brw->ctx;

   /* _NEW_POLYGON */
   if (!ctx->Polygon.StippleFlag)
      return;

   BEGIN_BATCH(2);
   OUT_BATCH(_3DSTATE_POLY_STIPPLE_OFFSET << 16 | (2-2));

   /* _NEW_BUFFERS
    *
    * If we're drawing to a system window we have to invert the Y axis
    * in order to match the OpenGL pixel coordinate system, and our
    * offset must be matched to the window position.  If we're drawing
    * to a user-created FBO then our native pixel coordinate system
    * works just fine, and there's no window system to worry about.
    */
   if (_mesa_is_winsys_fbo(ctx->DrawBuffer))
      OUT_BATCH((32 - (_mesa_geometric_height(ctx->DrawBuffer) & 31)) & 31);
   else
      OUT_BATCH(0);
   ADVANCE_BATCH();
}
/**
 * Update a gl_framebuffer's derived state.
 *
 * Specifically, update these framebuffer fields:
 *    _ColorDrawBuffers
 *    _NumColorDrawBuffers
 *    _ColorReadBuffer
 *
 * If the framebuffer is user-created, make sure it's complete.
 *
 * The following functions (at least) can effect framebuffer state:
 * glReadBuffer, glDrawBuffer, glDrawBuffersARB, glFramebufferRenderbufferEXT,
 * glRenderbufferStorageEXT.
 */
static void
update_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
{
   if (_mesa_is_winsys_fbo(fb)) {
      /* This is a window-system framebuffer */
      /* Need to update the FB's GL_DRAW_BUFFER state to match the
       * context state (GL_READ_BUFFER too).
       */
      if (fb->ColorDrawBuffer[0] != ctx->Color.DrawBuffer[0]) {
         _mesa_drawbuffers(ctx, fb, ctx->Const.MaxDrawBuffers,
                           ctx->Color.DrawBuffer, NULL);
      }
   }
   else {
      /* This is a user-created framebuffer.
       * Completeness only matters for user-created framebuffers.
       */
      if (fb->_Status != GL_FRAMEBUFFER_COMPLETE) {
         _mesa_test_framebuffer_completeness(ctx, fb);
      }
   }

   /* Strictly speaking, we don't need to update the draw-state
    * if this FB is bound as ctx->ReadBuffer (and conversely, the
    * read-state if this FB is bound as ctx->DrawBuffer), but no
    * harm.
    */
   update_color_draw_buffers(ctx, fb);
   update_color_read_buffer(ctx, fb);

   compute_depth_max(fb);
}
static void upload_polygon_stipple_offset(struct brw_context *brw)
{
   struct intel_context *intel = &brw->intel;
   struct gl_context *ctx = &brw->intel.ctx;

   /* _NEW_POLYGON */
   if (!ctx->Polygon.StippleFlag)
      return;

   if (intel->gen == 6)
      intel_emit_post_sync_nonzero_flush(intel);

   BEGIN_BATCH(2);
   OUT_BATCH(_3DSTATE_POLY_STIPPLE_OFFSET << 16 | (2-2));

   /* _NEW_BUFFERS
    *
    * If we're drawing to a system window we have to invert the Y axis
    * in order to match the OpenGL pixel coordinate system, and our
    * offset must be matched to the window position.  If we're drawing
    * to a user-created FBO then our native pixel coordinate system
    * works just fine, and there's no window system to worry about.
    */
   if (_mesa_is_winsys_fbo(brw->intel.ctx.DrawBuffer))
      OUT_BATCH((32 - (ctx->DrawBuffer->Height & 31)) & 31);
   else
      OUT_BATCH(0);
   CACHED_BATCH();
}
static void upload_polygon_stipple(struct brw_context *brw)
{
   struct intel_context *intel = &brw->intel;
   struct gl_context *ctx = &brw->intel.ctx;
   GLuint i;

   /* _NEW_POLYGON */
   if (!ctx->Polygon.StippleFlag)
      return;

   if (intel->gen == 6)
      intel_emit_post_sync_nonzero_flush(intel);

   BEGIN_BATCH(33);
   OUT_BATCH(_3DSTATE_POLY_STIPPLE_PATTERN << 16 | (33 - 2));

   /* Polygon stipple is provided in OpenGL order, i.e. bottom
    * row first.  If we're rendering to a window (i.e. the
    * default frame buffer object, 0), then we need to invert
    * it to match our pixel layout.  But if we're rendering
    * to a FBO (i.e. any named frame buffer object), we *don't*
    * need to invert - we already match the layout.
    */
   if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) {
      for (i = 0; i < 32; i++)
	  OUT_BATCH(ctx->PolygonStipple[31 - i]); /* invert */
   }
   else {
      for (i = 0; i < 32; i++)
	 OUT_BATCH(ctx->PolygonStipple[i]);
   }
   CACHED_BATCH();
}
Esempio n. 8
0
/**
 * Update the viewport transformation matrix.  Depends on:
 *  - viewport pos/size
 *  - depthrange
 *  - window pos/size or FBO size
 */
void
intelCalcViewport(struct gl_context * ctx)
{
   struct intel_context *intel = intel_context(ctx);

   if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) {
      _math_matrix_viewport(&intel->ViewportMatrix,
			    ctx->Viewport.X,
			    ctx->DrawBuffer->Height - ctx->Viewport.Y,
			    ctx->Viewport.Width,
			    -ctx->Viewport.Height,
			    ctx->Viewport.Near,
			    ctx->Viewport.Far,
			    1.0);
   } else {
      _math_matrix_viewport(&intel->ViewportMatrix,
			    ctx->Viewport.X,
			    ctx->Viewport.Y,
			    ctx->Viewport.Width,
			    ctx->Viewport.Height,
			    ctx->Viewport.Near,
			    ctx->Viewport.Far,
			    1.0);
   }
}
/**
 * XXX THIS IS OBSOLETE - drivers should take care of detecting window
 * size changes and act accordingly, likely calling _mesa_resize_framebuffer().
 *
 * GL_MESA_resize_buffers extension.
 *
 * When this function is called, we'll ask the window system how large
 * the current window is.  If it's a new size, we'll call the driver's
 * ResizeBuffers function.  The driver will then resize its color buffers
 * as needed, and maybe call the swrast's routine for reallocating
 * swrast-managed depth/stencil/accum/etc buffers.
 * \note This function should only be called through the GL API, not
 * from device drivers (as was done in the past).
 */
void
_mesa_resizebuffers( struct gl_context *ctx )
{
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx );

   if (MESA_VERBOSE & VERBOSE_API)
      _mesa_debug(ctx, "glResizeBuffersMESA\n");

   if (!ctx->Driver.GetBufferSize) {
      return;
   }

   if (ctx->WinSysDrawBuffer) {
      GLuint newWidth, newHeight;
      struct gl_framebuffer *buffer = ctx->WinSysDrawBuffer;

      assert(_mesa_is_winsys_fbo(buffer));

      /* ask device driver for size of output buffer */
      ctx->Driver.GetBufferSize( buffer, &newWidth, &newHeight );

      /* see if size of device driver's color buffer (window) has changed */
      if (buffer->Width != newWidth || buffer->Height != newHeight) {
         if (ctx->Driver.ResizeBuffers)
            ctx->Driver.ResizeBuffers(ctx, buffer, newWidth, newHeight );
      }
   }

   if (ctx->WinSysReadBuffer
       && ctx->WinSysReadBuffer != ctx->WinSysDrawBuffer) {
      GLuint newWidth, newHeight;
      struct gl_framebuffer *buffer = ctx->WinSysReadBuffer;

      assert(_mesa_is_winsys_fbo(buffer));

      /* ask device driver for size of read buffer */
      ctx->Driver.GetBufferSize( buffer, &newWidth, &newHeight );

      /* see if size of device driver's color buffer (window) has changed */
      if (buffer->Width != newWidth || buffer->Height != newHeight) {
         if (ctx->Driver.ResizeBuffers)
            ctx->Driver.ResizeBuffers(ctx, buffer, newWidth, newHeight );
      }
   }

   ctx->NewState |= _NEW_BUFFERS;  /* to update scissor / window bounds */
}
Esempio n. 10
0
/**
 * Cast wrapper to convert a struct gl_framebuffer to an st_framebuffer.
 * Return NULL if the struct gl_framebuffer is a user-created framebuffer.
 * We'll only return non-null for window system framebuffers.
 * Note that this function may fail.
 */
static INLINE struct st_framebuffer *
st_ws_framebuffer(struct gl_framebuffer *fb)
{
   /* FBO cannot be casted.  See st_new_framebuffer */
   if (fb && _mesa_is_winsys_fbo(fb))
      return (struct st_framebuffer *) fb;
   return NULL;
}
Esempio n. 11
0
/**
 * Update the current drawbuffer's _ColorDrawBufferIndex[] list, etc.
 * from the context's Color.DrawBuffer[] state.
 * Use when changing contexts.
 */
void
_mesa_update_draw_buffers(struct gl_context *ctx)
{
   /* should be a window system FBO */
   assert(_mesa_is_winsys_fbo(ctx->DrawBuffer));

   _mesa_drawbuffers(ctx, ctx->DrawBuffer, ctx->Const.MaxDrawBuffers,
                     ctx->Color.DrawBuffer, NULL);
}
Esempio n. 12
0
static void
intel_viewport(struct gl_context *ctx)
{
   struct brw_context *brw = brw_context(ctx);
   __DRIcontext *driContext = brw->driContext;

   if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) {
      dri2InvalidateDrawable(driContext->driDrawablePriv);
      dri2InvalidateDrawable(driContext->driReadablePriv);
   }
}
Esempio n. 13
0
/**
 * Check if we're about to draw into the front color buffer.
 * If so, set the intel->front_buffer_dirty field to true.
 */
void
intel_check_front_buffer_rendering(struct intel_context *intel)
{
   const struct gl_framebuffer *fb = intel->ctx.DrawBuffer;
   if (_mesa_is_winsys_fbo(fb)) {
      /* drawing to window system buffer */
      if (fb->_NumColorDrawBuffers > 0) {
         if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) {
	    intel->front_buffer_dirty = true;
	 }
      }
   }
}
static void
intel_noninvalidate_viewport(struct gl_context *ctx)
{
    struct intel_context *intel = intel_context(ctx);
    __DRIcontext *driContext = intel->driContext;

    intelCalcViewport(ctx);

    if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) {
       dri2InvalidateDrawable(driContext->driDrawablePriv);
       dri2InvalidateDrawable(driContext->driReadablePriv);
    }
}
Esempio n. 15
0
static void
intel_viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
{
    struct intel_context *intel = intel_context(ctx);
    __DRIcontext *driContext = intel->driContext;

    if (intel->saved_viewport)
	intel->saved_viewport(ctx, x, y, w, h);

    if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) {
       dri2InvalidateDrawable(driContext->driDrawablePriv);
       dri2InvalidateDrawable(driContext->driReadablePriv);
    }
}
Esempio n. 16
0
/**
 * Update the current drawbuffer's _ColorDrawBufferIndex[] list, etc.
 * from the context's Color.DrawBuffer[] state.
 * Use when changing contexts.
 */
void
_mesa_update_draw_buffers(struct gl_context *ctx)
{
   GLenum buffers[MAX_DRAW_BUFFERS];
   GLuint i;

   /* should be a window system FBO */
   assert(_mesa_is_winsys_fbo(ctx->DrawBuffer));

   for (i = 0; i < ctx->Const.MaxDrawBuffers; i++)
      buffers[i] = ctx->Color.DrawBuffer[i];

   _mesa_drawbuffers(ctx, ctx->Const.MaxDrawBuffers, buffers, NULL);
}
Esempio n. 17
0
/**
 * Like \sa _mesa_drawbuffers(), this is a helper function for setting
 * GL_READ_BUFFER state in the context and current FBO.
 * \param ctx  the rendering context
 * \param buffer  GL_FRONT, GL_BACK, GL_COLOR_ATTACHMENT0, etc.
 * \param bufferIndex  the numerical index corresponding to 'buffer'
 */
void
_mesa_readbuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
                 GLenum buffer, GLint bufferIndex)
{
   if ((fb == ctx->ReadBuffer) && _mesa_is_winsys_fbo(fb)) {
      /* Only update the per-context READ_BUFFER state if we're bound to
       * a window-system framebuffer.
       */
      ctx->Pixel.ReadBuffer = buffer;
   }

   fb->ColorReadBuffer = buffer;
   fb->_ColorReadBufferIndex = bufferIndex;

   ctx->NewState |= _NEW_BUFFERS;
}
Esempio n. 18
0
static void
nouveau_flush(struct gl_context *ctx)
{
	struct nouveau_context *nctx = to_nouveau_context(ctx);
	struct nouveau_pushbuf *push = context_push(ctx);

	PUSH_KICK(push);

	if (_mesa_is_winsys_fbo(ctx->DrawBuffer) &&
	    ctx->DrawBuffer->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) {
		__DRIscreen *screen = nctx->screen->dri_screen;
		__DRIdri2LoaderExtension *dri2 = screen->dri2.loader;
		__DRIdrawable *drawable = nctx->dri_context->driDrawablePriv;

		dri2->flushFrontBuffer(drawable, drawable->loaderPrivate);
	}
}
Esempio n. 19
0
/* =============================================================
 * Hardware clipping
 */
static void
i830Scissor(struct gl_context * ctx)
{
   struct i830_context *i830 = i830_context(ctx);
   int x1, y1, x2, y2;

   if (!ctx->DrawBuffer)
      return;

   DBG("%s %d,%d %dx%d\n", __func__,
       ctx->Scissor.ScissorArray[0].X,     ctx->Scissor.ScissorArray[0].Y,
       ctx->Scissor.ScissorArray[0].Width, ctx->Scissor.ScissorArray[0].Height);

   if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) {
      x1 = ctx->Scissor.ScissorArray[0].X;
      y1 = ctx->DrawBuffer->Height - (ctx->Scissor.ScissorArray[0].Y
                                      + ctx->Scissor.ScissorArray[0].Height);
      x2 = ctx->Scissor.ScissorArray[0].X
         + ctx->Scissor.ScissorArray[0].Width - 1;
      y2 = y1 + ctx->Scissor.ScissorArray[0].Height - 1;
      DBG("%s %d..%d,%d..%d (inverted)\n", __func__, x1, x2, y1, y2);
   }
   else {
      /* FBO - not inverted
       */
      x1 = ctx->Scissor.ScissorArray[0].X;
      y1 = ctx->Scissor.ScissorArray[0].Y;
      x2 = ctx->Scissor.ScissorArray[0].X
         + ctx->Scissor.ScissorArray[0].Width - 1;
      y2 = ctx->Scissor.ScissorArray[0].Y
         + ctx->Scissor.ScissorArray[0].Height - 1;
      DBG("%s %d..%d,%d..%d (not inverted)\n", __func__, x1, x2, y1, y2);
   }

   x1 = CLAMP(x1, 0, ctx->DrawBuffer->Width - 1);
   y1 = CLAMP(y1, 0, ctx->DrawBuffer->Height - 1);
   x2 = CLAMP(x2, 0, ctx->DrawBuffer->Width - 1);
   y2 = CLAMP(y2, 0, ctx->DrawBuffer->Height - 1);
   
   DBG("%s %d..%d,%d..%d (clamped)\n", __func__, x1, x2, y1, y2);

   I830_STATECHANGE(i830, I830_UPLOAD_BUFFERS);
   i830->state.Buffer[I830_DESTREG_SR1] = (y1 << 16) | (x1 & 0xffff);
   i830->state.Buffer[I830_DESTREG_SR2] = (y2 << 16) | (x2 & 0xffff);
}
Esempio n. 20
0
static void
intelReadBuffer(struct gl_context * ctx, GLenum mode)
{
   if (ctx->DrawBuffer && _mesa_is_winsys_fbo(ctx->DrawBuffer)) {
      struct intel_context *const intel = intel_context(ctx);
      const bool was_front_buffer_reading =
	intel->is_front_buffer_reading;

      intel->is_front_buffer_reading = (mode == GL_FRONT_LEFT)
	|| (mode == GL_FRONT);

      /* If we weren't front-buffer reading before but we are now,
       * invalidate our DRI drawable so we'll ask for new buffers
       * (including the fake front) before we start reading again.
       */
      if (!was_front_buffer_reading && intel->is_front_buffer_reading)
	 dri2InvalidateDrawable(intel->driContext->driReadablePriv);
   }
}
/**
 * Resize the given framebuffer's renderbuffers to the new width and height.
 * This should only be used for window-system framebuffers, not
 * user-created renderbuffers (i.e. made with GL_EXT_framebuffer_object).
 * This will typically be called directly from a device driver.
 *
 * \note it's possible for ctx to be null since a window can be resized
 * without a currently bound rendering context.
 */
void
_mesa_resize_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
                         GLuint width, GLuint height)
{
   GLuint i;

   /* XXX I think we could check if the size is not changing
    * and return early.
    */

   /* Can only resize win-sys framebuffer objects */
   assert(_mesa_is_winsys_fbo(fb));

   for (i = 0; i < BUFFER_COUNT; i++) {
      struct gl_renderbuffer_attachment *att = &fb->Attachment[i];
      if (att->Type == GL_RENDERBUFFER_EXT && att->Renderbuffer) {
         struct gl_renderbuffer *rb = att->Renderbuffer;
         /* only resize if size is changing */
         if (rb->Width != width || rb->Height != height) {
            if (rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height)) {
               assert(rb->Width == width);
               assert(rb->Height == height);
            }
            else {
               _mesa_error(ctx, GL_OUT_OF_MEMORY, "Resizing framebuffer");
               /* no return */
            }
         }
      }
   }

   fb->Width = width;
   fb->Height = height;

   if (ctx) {
      /* update scissor / window bounds */
      _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer);
      /* Signal new buffer state so that swrast will update its clipping
       * info (the CLIP_BIT flag).
       */
      ctx->NewState |= _NEW_BUFFERS;
   }
}
static void
intel_flush_front(struct gl_context *ctx)
{
   struct intel_context *intel = intel_context(ctx);
    __DRIcontext *driContext = intel->driContext;
    __DRIdrawable *driDrawable = driContext->driDrawablePriv;
    __DRIscreen *const screen = intel->intelScreen->driScrnPriv;

    if (intel->front_buffer_dirty && _mesa_is_winsys_fbo(ctx->DrawBuffer)) {
      if (flushFront(screen) && 
          driDrawable &&
          driDrawable->loaderPrivate) {
         flushFront(screen)(driDrawable, driDrawable->loaderPrivate);

	 /* We set the dirty bit in intel_prepare_render() if we're
	  * front buffer rendering once we get there.
	  */
	 intel->front_buffer_dirty = false;
      }
   }
}
Esempio n. 23
0
/* =============================================================
 * Hardware clipping
 */
static void
i915Scissor(struct gl_context * ctx, GLint x, GLint y, GLsizei w, GLsizei h)
{
   struct i915_context *i915 = I915_CONTEXT(ctx);
   int x1, y1, x2, y2;

   if (!ctx->DrawBuffer)
      return;

   DBG("%s %d,%d %dx%d\n", __FUNCTION__, x, y, w, h);

   if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) {
      x1 = x;
      y1 = ctx->DrawBuffer->Height - (y + h);
      x2 = x + w - 1;
      y2 = y1 + h - 1;
      DBG("%s %d..%d,%d..%d (inverted)\n", __FUNCTION__, x1, x2, y1, y2);
   }
   else {
      /* FBO - not inverted
       */
      x1 = x;
      y1 = y;
      x2 = x + w - 1;
      y2 = y + h - 1;
      DBG("%s %d..%d,%d..%d (not inverted)\n", __FUNCTION__, x1, x2, y1, y2);
   }
   
   x1 = CLAMP(x1, 0, ctx->DrawBuffer->Width - 1);
   y1 = CLAMP(y1, 0, ctx->DrawBuffer->Height - 1);
   x2 = CLAMP(x2, 0, ctx->DrawBuffer->Width - 1);
   y2 = CLAMP(y2, 0, ctx->DrawBuffer->Height - 1);
   
   DBG("%s %d..%d,%d..%d (clamped)\n", __FUNCTION__, x1, x2, y1, y2);

   I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS);
   i915->state.Buffer[I915_DESTREG_SR1] = (y1 << 16) | (x1 & 0xffff);
   i915->state.Buffer[I915_DESTREG_SR2] = (y2 << 16) | (x2 & 0xffff);
}
Esempio n. 24
0
bool
intel_copy_texsubimage(struct intel_context *intel,
                       struct intel_texture_image *intelImage,
                       GLint dstx, GLint dsty,
                       struct intel_renderbuffer *irb,
                       GLint x, GLint y, GLsizei width, GLsizei height)
{
    struct gl_context *ctx = &intel->ctx;
    struct intel_region *region;
    const GLenum internalFormat = intelImage->base.Base.InternalFormat;
    bool copy_supported = false;
    bool copy_supported_with_alpha_override = false;

    intel_prepare_render(intel);

    if (!intelImage->mt || !irb || !irb->mt) {
        if (unlikely(INTEL_DEBUG & DEBUG_PERF))
            fprintf(stderr, "%s fail %p %p (0x%08x)\n",
                    __FUNCTION__, intelImage->mt, irb, internalFormat);
        return false;
    } else {
        region = irb->mt->region;
        assert(region);
    }

    /* According to the Ivy Bridge PRM, Vol1 Part4, section 1.2.1.2 (Graphics
     * Data Size Limitations):
     *
     *    The BLT engine is capable of transferring very large quantities of
     *    graphics data. Any graphics data read from and written to the
     *    destination is permitted to represent a number of pixels that
     *    occupies up to 65,536 scan lines and up to 32,768 bytes per scan line
     *    at the destination. The maximum number of pixels that may be
     *    represented per scan line’s worth of graphics data depends on the
     *    color depth.
     *
     * Furthermore, intelEmitCopyBlit (which is called below) uses a signed
     * 16-bit integer to represent buffer pitch, so it can only handle buffer
     * pitches < 32k.
     *
     * As a result of these two limitations, we can only use the blitter to do
     * this copy when the region's pitch is less than 32k.
     */
    if (region->pitch >= 32768)
        return false;

    if (intelImage->base.Base.TexObject->Target == GL_TEXTURE_1D_ARRAY ||
            intelImage->base.Base.TexObject->Target == GL_TEXTURE_2D_ARRAY) {
        perf_debug("no support for array textures\n");
    }

    copy_supported = intelImage->base.Base.TexFormat == intel_rb_format(irb);

    /* Converting ARGB8888 to XRGB8888 is trivial: ignore the alpha bits */
    if (intel_rb_format(irb) == MESA_FORMAT_ARGB8888 &&
            intelImage->base.Base.TexFormat == MESA_FORMAT_XRGB8888) {
        copy_supported = true;
    }

    /* Converting XRGB8888 to ARGB8888 requires setting the alpha bits to 1.0 */
    if (intel_rb_format(irb) == MESA_FORMAT_XRGB8888 &&
            intelImage->base.Base.TexFormat == MESA_FORMAT_ARGB8888) {
        copy_supported_with_alpha_override = true;
    }

    if (!copy_supported && !copy_supported_with_alpha_override) {
        if (unlikely(INTEL_DEBUG & DEBUG_PERF))
            fprintf(stderr, "%s mismatched formats %s, %s\n",
                    __FUNCTION__,
                    _mesa_get_format_name(intelImage->base.Base.TexFormat),
                    _mesa_get_format_name(intel_rb_format(irb)));
        return false;
    }

    {
        GLuint image_x, image_y;
        GLshort src_pitch;

        /* get dest x/y in destination texture */
        intel_miptree_get_image_offset(intelImage->mt,
                                       intelImage->base.Base.Level,
                                       intelImage->base.Base.Face,
                                       &image_x, &image_y);

        /* The blitter can't handle Y-tiled buffers. */
        if (intelImage->mt->region->tiling == I915_TILING_Y) {
            return false;
        }

        if (_mesa_is_winsys_fbo(ctx->ReadBuffer)) {
            /* Flip vertical orientation for system framebuffers */
            y = ctx->ReadBuffer->Height - (y + height);
            src_pitch = -region->pitch;
        } else {
            /* reading from a FBO, y is already oriented the way we like */
            src_pitch = region->pitch;
        }

        /* blit from src buffer to texture */
        if (!intelEmitCopyBlit(intel,
                               intelImage->mt->cpp,
                               src_pitch,
                               region->bo,
                               0,
                               region->tiling,
                               intelImage->mt->region->pitch,
                               intelImage->mt->region->bo,
                               0,
                               intelImage->mt->region->tiling,
                               irb->draw_x + x, irb->draw_y + y,
                               image_x + dstx, image_y + dsty,
                               width, height,
                               GL_COPY)) {
            return false;
        }
    }

    if (copy_supported_with_alpha_override)
        intel_set_teximage_alpha_to_one(ctx, intelImage);

    return true;
}
Esempio n. 25
0
/**
 * Use blitting to clear the renderbuffers named by 'flags'.
 * Note: we can't use the ctx->DrawBuffer->_ColorDrawBufferIndexes field
 * since that might include software renderbuffers or renderbuffers
 * which we're clearing with triangles.
 * \param mask  bitmask of BUFFER_BIT_* values indicating buffers to clear
 */
GLbitfield
intelClearWithBlit(struct gl_context *ctx, GLbitfield mask)
{
   struct intel_context *intel = intel_context(ctx);
   struct gl_framebuffer *fb = ctx->DrawBuffer;
   GLuint clear_depth_value, clear_depth_mask;
   GLint cx, cy, cw, ch;
   GLbitfield fail_mask = 0;
   BATCH_LOCALS;

   /* Note: we don't use this function on Gen7+ hardware, so we can safely
    * ignore fast color clear issues.
    */
   assert(intel->gen < 7);

   /*
    * Compute values for clearing the buffers.
    */
   clear_depth_value = 0;
   clear_depth_mask = 0;
   if (mask & BUFFER_BIT_DEPTH) {
      clear_depth_value = (GLuint) (fb->_DepthMax * ctx->Depth.Clear);
      clear_depth_mask = XY_BLT_WRITE_RGB;
   }
   if (mask & BUFFER_BIT_STENCIL) {
      clear_depth_value |= (ctx->Stencil.Clear & 0xff) << 24;
      clear_depth_mask |= XY_BLT_WRITE_ALPHA;
   }

   cx = fb->_Xmin;
   if (_mesa_is_winsys_fbo(fb))
      cy = ctx->DrawBuffer->Height - fb->_Ymax;
   else
      cy = fb->_Ymin;
   cw = fb->_Xmax - fb->_Xmin;
   ch = fb->_Ymax - fb->_Ymin;

   if (cw == 0 || ch == 0)
      return 0;

   /* Loop over all renderbuffers */
   mask &= (1 << BUFFER_COUNT) - 1;
   while (mask) {
      GLuint buf = ffs(mask) - 1;
      bool is_depth_stencil = buf == BUFFER_DEPTH || buf == BUFFER_STENCIL;
      struct intel_renderbuffer *irb;
      int x1, y1, x2, y2;
      uint32_t clear_val;
      uint32_t BR13, CMD;
      struct intel_region *region;
      int pitch, cpp;
      drm_intel_bo *aper_array[2];

      mask &= ~(1 << buf);

      irb = intel_get_renderbuffer(fb, buf);
      if (irb && irb->mt) {
	 region = irb->mt->region;
	 assert(region);
	 assert(region->bo);
      } else {
         fail_mask |= 1 << buf;
         continue;
      }

      /* OK, clear this renderbuffer */
      x1 = cx + irb->draw_x;
      y1 = cy + irb->draw_y;
      x2 = cx + cw + irb->draw_x;
      y2 = cy + ch + irb->draw_y;

      pitch = region->pitch;
      cpp = region->cpp;

      DBG("%s dst:buf(%p)/%d %d,%d sz:%dx%d\n",
	  __FUNCTION__,
	  region->bo, pitch,
	  x1, y1, x2 - x1, y2 - y1);

      BR13 = 0xf0 << 16;
      CMD = XY_COLOR_BLT_CMD;

      /* Setup the blit command */
      if (cpp == 4) {
	 if (is_depth_stencil) {
	    CMD |= clear_depth_mask;
	 } else {
	    /* clearing RGBA */
	    CMD |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
	 }
      }

      assert(region->tiling != I915_TILING_Y);

      BR13 |= pitch;

      if (is_depth_stencil) {
	 clear_val = clear_depth_value;
      } else {
	 uint8_t clear[4];
	 GLfloat *color = ctx->Color.ClearColor.f;

	 _mesa_unclamped_float_rgba_to_ubyte(clear, color);

	 switch (intel_rb_format(irb)) {
	 case MESA_FORMAT_ARGB8888:
	 case MESA_FORMAT_XRGB8888:
	    clear_val = PACK_COLOR_8888(clear[3], clear[0],
					clear[1], clear[2]);
	    break;
	 case MESA_FORMAT_RGB565:
	    clear_val = PACK_COLOR_565(clear[0], clear[1], clear[2]);
	    break;
	 case MESA_FORMAT_ARGB4444:
	    clear_val = PACK_COLOR_4444(clear[3], clear[0],
					clear[1], clear[2]);
	    break;
	 case MESA_FORMAT_ARGB1555:
	    clear_val = PACK_COLOR_1555(clear[3], clear[0],
					clear[1], clear[2]);
	    break;
	 case MESA_FORMAT_A8:
	    clear_val = PACK_COLOR_8888(clear[3], clear[3],
					clear[3], clear[3]);
	    break;
	 default:
	    fail_mask |= 1 << buf;
	    continue;
	 }
      }

      BR13 |= br13_for_cpp(cpp);

      assert(x1 < x2);
      assert(y1 < y2);

      /* do space check before going any further */
      aper_array[0] = intel->batch.bo;
      aper_array[1] = region->bo;

      if (drm_intel_bufmgr_check_aperture_space(aper_array,
						ARRAY_SIZE(aper_array)) != 0) {
	 intel_batchbuffer_flush(intel);
      }

      BEGIN_BATCH(6);
      OUT_BATCH(CMD | (6 - 2));
      OUT_BATCH(BR13);
      OUT_BATCH((y1 << 16) | x1);
      OUT_BATCH((y2 << 16) | x2);
      OUT_RELOC_FENCED(region->bo,
		       I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
		       0);
      OUT_BATCH(clear_val);
      ADVANCE_BATCH();

      if (intel->always_flush_cache)
	 intel_batchbuffer_emit_mi_flush(intel);

      if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL)
	 mask &= ~(BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL);
   }

   return fail_mask;
}
Esempio n. 26
0
/**
 * Helper function to set the GL_DRAW_BUFFER state in the context and
 * current FBO.  Called via glDrawBuffer(), glDrawBuffersARB()
 *
 * All error checking will have been done prior to calling this function
 * so nothing should go wrong at this point.
 *
 * \param ctx  current context
 * \param n    number of color outputs to set
 * \param buffers  array[n] of colorbuffer names, like GL_LEFT.
 * \param destMask  array[n] of BUFFER_BIT_* bitmasks which correspond to the
 *                  colorbuffer names.  (i.e. GL_FRONT_AND_BACK =>
 *                  BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT).
 */
void
_mesa_drawbuffers(struct gl_context *ctx, GLuint n, const GLenum *buffers,
                  const GLbitfield *destMask)
{
   struct gl_framebuffer *fb = ctx->DrawBuffer;
   GLbitfield mask[MAX_DRAW_BUFFERS];
   GLuint buf;

   if (!destMask) {
      /* compute destMask values now */
      const GLbitfield supportedMask = supported_buffer_bitmask(ctx, fb);
      GLuint output;
      for (output = 0; output < n; output++) {
         mask[output] = draw_buffer_enum_to_bitmask(ctx, buffers[output]);
         ASSERT(mask[output] != BAD_MASK);
         mask[output] &= supportedMask;
      }
      destMask = mask;
   }

   /*
    * destMask[0] may have up to four bits set
    * (ex: glDrawBuffer(GL_FRONT_AND_BACK)).
    * Otherwise, destMask[x] can only have one bit set.
    */
   if (n > 0 && _mesa_bitcount(destMask[0]) > 1) {
      GLuint count = 0, destMask0 = destMask[0];
      while (destMask0) {
         GLint bufIndex = ffs(destMask0) - 1;
         if (fb->_ColorDrawBufferIndexes[count] != bufIndex) {
            updated_drawbuffers(ctx);
            fb->_ColorDrawBufferIndexes[count] = bufIndex;
         }
         count++;
         destMask0 &= ~(1 << bufIndex);
      }
      fb->ColorDrawBuffer[0] = buffers[0];
      fb->_NumColorDrawBuffers = count;
   }
   else {
      GLuint count = 0;
      for (buf = 0; buf < n; buf++ ) {
         if (destMask[buf]) {
            GLint bufIndex = ffs(destMask[buf]) - 1;
            /* only one bit should be set in the destMask[buf] field */
            ASSERT(_mesa_bitcount(destMask[buf]) == 1);
            if (fb->_ColorDrawBufferIndexes[buf] != bufIndex) {
	       updated_drawbuffers(ctx);
               fb->_ColorDrawBufferIndexes[buf] = bufIndex;
            }
            count = buf + 1;
         }
         else {
            if (fb->_ColorDrawBufferIndexes[buf] != -1) {
	       updated_drawbuffers(ctx);
               fb->_ColorDrawBufferIndexes[buf] = -1;
            }
         }
         fb->ColorDrawBuffer[buf] = buffers[buf];
      }
      fb->_NumColorDrawBuffers = count;
   }

   /* set remaining outputs to -1 (GL_NONE) */
   for (buf = fb->_NumColorDrawBuffers; buf < ctx->Const.MaxDrawBuffers; buf++) {
      if (fb->_ColorDrawBufferIndexes[buf] != -1) {
         updated_drawbuffers(ctx);
         fb->_ColorDrawBufferIndexes[buf] = -1;
      }
   }
   for (buf = n; buf < ctx->Const.MaxDrawBuffers; buf++) {
      fb->ColorDrawBuffer[buf] = GL_NONE;
   }

   if (_mesa_is_winsys_fbo(fb)) {
      /* also set context drawbuffer state */
      for (buf = 0; buf < ctx->Const.MaxDrawBuffers; buf++) {
         if (ctx->Color.DrawBuffer[buf] != fb->ColorDrawBuffer[buf]) {
	    updated_drawbuffers(ctx);
            ctx->Color.DrawBuffer[buf] = fb->ColorDrawBuffer[buf];
         }
      }
   }
}
Esempio n. 27
0
/**
 * Called by glDrawBuffersARB; specifies the destination color renderbuffers
 * for N fragment program color outputs.
 * \sa _mesa_DrawBuffer
 * \param n  number of outputs
 * \param buffers  array [n] of renderbuffer names.  Unlike glDrawBuffer, the
 *                 names cannot specify more than one buffer.  For example,
 *                 GL_FRONT_AND_BACK is illegal.
 */
void GLAPIENTRY
_mesa_DrawBuffers(GLsizei n, const GLenum *buffers)
{
   GLint output;
   GLbitfield usedBufferMask, supportedMask;
   GLbitfield destMask[MAX_DRAW_BUFFERS];
   GET_CURRENT_CONTEXT(ctx);

   FLUSH_VERTICES(ctx, 0);

   /* Turns out n==0 is a valid input that should not produce an error.
    * The remaining code below correctly handles the n==0 case.
    *
    * From the OpenGL 3.0 specification, page 258:
    * "An INVALID_VALUE error is generated if n is greater than
    *  MAX_DRAW_BUFFERS."
    */
   if (n < 0 || n > (GLsizei) ctx->Const.MaxDrawBuffers) {
      _mesa_error(ctx, GL_INVALID_VALUE, "glDrawBuffersARB(n)");
      return;
   }

   supportedMask = supported_buffer_bitmask(ctx, ctx->DrawBuffer);
   usedBufferMask = 0x0;

   /* From the ES 3.0 specification, page 180:
    * "If the GL is bound to the default framebuffer, then n must be 1
    *  and the constant must be BACK or NONE."
    */
   if (_mesa_is_gles3(ctx) && _mesa_is_winsys_fbo(ctx->DrawBuffer) &&
       (n != 1 || (buffers[0] != GL_NONE && buffers[0] != GL_BACK))) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffers(buffer)");
      return;
   }

   /* complicated error checking... */
   for (output = 0; output < n; output++) {
      if (buffers[output] == GL_NONE) {
         destMask[output] = 0x0;
      }
      else {
         /* Page 259 (page 275 of the PDF) in section 4.2.1 of the OpenGL 3.0
          * spec (20080923) says:
          *
          *     "If the GL is bound to a framebuffer object and DrawBuffers is
          *     supplied with [...] COLOR_ATTACHMENTm where m is greater than
          *     or equal to the value of MAX_COLOR_ATTACHMENTS, then the error
          *     INVALID_OPERATION results."
          */
         if (_mesa_is_user_fbo(ctx->DrawBuffer) && buffers[output] >=
             GL_COLOR_ATTACHMENT0 + ctx->Const.MaxDrawBuffers) {
            _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffersARB(buffer)");
            return;
         }

         destMask[output] = draw_buffer_enum_to_bitmask(ctx, buffers[output]);

         /* From the OpenGL 3.0 specification, page 258:
          * "Each buffer listed in bufs must be one of the values from tables
          *  4.5 or 4.6.  Otherwise, an INVALID_ENUM error is generated.
          */
         if (destMask[output] == BAD_MASK) {
            _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffersARB(buffer)");
            return;
         }         

         /* From the OpenGL 4.0 specification, page 256:
          * "For both the default framebuffer and framebuffer objects, the
          *  constants FRONT, BACK, LEFT, RIGHT, and FRONT_AND_BACK are not
          *  valid in the bufs array passed to DrawBuffers, and will result in
          *  the error INVALID_ENUM. This restriction is because these
          *  constants may themselves refer to multiple buffers, as shown in
          *  table 4.4."
          *  Previous versions of the OpenGL specification say INVALID_OPERATION,
          *  but the Khronos conformance tests expect INVALID_ENUM.
          */
         if (_mesa_bitcount(destMask[output]) > 1) {
            _mesa_error(ctx, GL_INVALID_ENUM, "glDrawBuffersARB(buffer)");
            return;
         }

         /* From the OpenGL 3.0 specification, page 259:
          * "If the GL is bound to the default framebuffer and DrawBuffers is
          *  supplied with a constant (other than NONE) that does not indicate
          *  any of the color buffers allocated to the GL context by the window
          *  system, the error INVALID_OPERATION will be generated.
          *
          *  If the GL is bound to a framebuffer object and DrawBuffers is
          *  supplied with a constant from table 4.6 [...] then the error
          *  INVALID_OPERATION results."
          */
         destMask[output] &= supportedMask;
         if (destMask[output] == 0) {
            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "glDrawBuffersARB(unsupported buffer)");
            return;
         }

         /* ES 3.0 is even more restrictive.  From the ES 3.0 spec, page 180:
          * "If the GL is bound to a framebuffer object, the ith buffer listed
          *  in bufs must be COLOR_ATTACHMENTi or NONE. [...] INVALID_OPERATION."
          */
         if (_mesa_is_gles3(ctx) && _mesa_is_user_fbo(ctx->DrawBuffer) &&
             buffers[output] != GL_NONE &&
             buffers[output] != GL_COLOR_ATTACHMENT0 + output) {
            _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawBuffers(buffer)");
            return;
         }

         /* From the OpenGL 3.0 specification, page 258:
          * "Except for NONE, a buffer may not appear more than once in the
          *  array pointed to by bufs.  Specifying a buffer more then once will
          *  result in the error INVALID_OPERATION."
          */
         if (destMask[output] & usedBufferMask) {
            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "glDrawBuffersARB(duplicated buffer)");
            return;
         }

         /* update bitmask */
         usedBufferMask |= destMask[output];
      }
   }

   /* OK, if we get here, there were no errors so set the new state */
   _mesa_drawbuffers(ctx, n, buffers, destMask);

   /*
    * Call device driver function.  Note that n can be equal to 0,
    * in which case we don't want to reference buffers[0], which
    * may not be valid.
    */
   if (ctx->Driver.DrawBuffers)
      ctx->Driver.DrawBuffers(ctx, n, buffers);
   else if (ctx->Driver.DrawBuffer)
      ctx->Driver.DrawBuffer(ctx, n > 0 ? buffers[0] : GL_NONE);
}
static bool
do_blit_drawpixels(struct gl_context * ctx,
		   GLint x, GLint y, GLsizei width, GLsizei height,
		   GLenum format, GLenum type,
		   const struct gl_pixelstore_attrib *unpack,
		   const GLvoid * pixels)
{
   struct brw_context *brw = brw_context(ctx);
   struct intel_buffer_object *src = intel_buffer_object(unpack->BufferObj);
   GLuint src_offset;
   drm_intel_bo *src_buffer;

   DBG("%s\n", __FUNCTION__);

   if (!intel_check_blit_fragment_ops(ctx, false))
      return false;

   if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) {
      DBG("%s: fallback due to MRT\n", __FUNCTION__);
      return false;
   }

   struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
   struct intel_renderbuffer *irb = intel_renderbuffer(rb);

   if (!_mesa_format_matches_format_and_type(irb->mt->format, format, type,
                                             false)) {
      DBG("%s: bad format for blit\n", __FUNCTION__);
      return false;
   }

   if (unpack->SwapBytes || unpack->LsbFirst ||
       unpack->SkipPixels || unpack->SkipRows) {
      DBG("%s: bad packing params\n", __FUNCTION__);
      return false;
   }

   int src_stride = _mesa_image_row_stride(unpack, width, format, type);
   bool src_flip = false;
   /* Mesa flips the src_stride for unpack->Invert, but we want our mt to have
    * a normal src_stride.
    */
   if (unpack->Invert) {
      src_stride = -src_stride;
      src_flip = true;
   }

   src_offset = (GLintptr)pixels;
   src_offset += _mesa_image_offset(2, unpack, width, height,
				    format, type, 0, 0, 0);

   intel_prepare_render(brw);

   src_buffer = intel_bufferobj_buffer(brw, src,
				       src_offset, width * height *
                                       irb->mt->cpp);

   struct intel_mipmap_tree *pbo_mt =
      intel_miptree_create_for_bo(brw,
                                  src_buffer,
                                  irb->mt->format,
                                  src_offset,
                                  width, height,
                                  src_stride, I915_TILING_NONE);
   if (!pbo_mt)
      return false;

   if (!intel_miptree_blit(brw,
                           pbo_mt, 0, 0,
                           0, 0, src_flip,
                           irb->mt, irb->mt_level, irb->mt_layer,
                           x, y, _mesa_is_winsys_fbo(ctx->DrawBuffer),
                           width, height, GL_COPY)) {
      DBG("%s: blit failed\n", __FUNCTION__);
      intel_miptree_release(&pbo_mt);
      return false;
   }

   intel_miptree_release(&pbo_mt);

   if (ctx->Query.CurrentOcclusionObject)
      ctx->Query.CurrentOcclusionObject->Result += width * height;

   intel_check_front_buffer_rendering(brw);

   DBG("%s: success\n", __FUNCTION__);
   return true;
}
Esempio n. 29
0
/*
 * Render a bitmap.
 */
static bool
do_blit_bitmap( struct gl_context *ctx, 
		GLint dstx, GLint dsty,
		GLsizei width, GLsizei height,
		const struct gl_pixelstore_attrib *unpack,
		const GLubyte *bitmap )
{
   struct intel_context *intel = intel_context(ctx);
   struct gl_framebuffer *fb = ctx->DrawBuffer;
   struct intel_renderbuffer *irb;
   GLfloat tmpColor[4];
   GLubyte ubcolor[4];
   GLuint color;
   GLsizei bitmap_width = width;
   GLsizei bitmap_height = height;
   GLint px, py;
   GLuint stipple[32];
   GLint orig_dstx = dstx;
   GLint orig_dsty = dsty;

   /* Update draw buffer bounds */
   _mesa_update_state(ctx);

   if (ctx->Depth.Test) {
      /* The blit path produces incorrect results when depth testing is on.
       * It seems the blit Z coord is always 1.0 (the far plane) so fragments
       * will likely be obscured by other, closer geometry.
       */
      return false;
   }

   intel_prepare_render(intel);

   if (fb->_NumColorDrawBuffers != 1) {
      perf_debug("accelerated glBitmap() only supports rendering to a "
                 "single color buffer\n");
      return false;
   }

   irb = intel_renderbuffer(fb->_ColorDrawBuffers[0]);

   if (_mesa_is_bufferobj(unpack->BufferObj)) {
      bitmap = map_pbo(ctx, width, height, unpack, bitmap);
      if (bitmap == NULL)
	 return true;	/* even though this is an error, we're done */
   }

   COPY_4V(tmpColor, ctx->Current.RasterColor);

   if (_mesa_need_secondary_color(ctx)) {
       ADD_3V(tmpColor, tmpColor, ctx->Current.RasterSecondaryColor);
   }

   UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[0], tmpColor[0]);
   UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[1], tmpColor[1]);
   UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[2], tmpColor[2]);
   UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[3], tmpColor[3]);

   switch (irb->mt->format) {
   case MESA_FORMAT_B8G8R8A8_UNORM:
   case MESA_FORMAT_B8G8R8X8_UNORM:
      color = PACK_COLOR_8888(ubcolor[3], ubcolor[0], ubcolor[1], ubcolor[2]);
      break;
   case MESA_FORMAT_B5G6R5_UNORM:
      color = PACK_COLOR_565(ubcolor[0], ubcolor[1], ubcolor[2]);
      break;
   default:
      perf_debug("Unsupported format %s in accelerated glBitmap()\n",
                 _mesa_get_format_name(irb->mt->format));
      return false;
   }

   if (!intel_check_blit_fragment_ops(ctx, tmpColor[3] == 1.0F))
      return false;

   /* Clip to buffer bounds and scissor. */
   if (!_mesa_clip_to_region(fb->_Xmin, fb->_Ymin,
			     fb->_Xmax, fb->_Ymax,
			     &dstx, &dsty, &width, &height))
      goto out;

   dsty = y_flip(fb, dsty, height);

#define DY 32
#define DX 32

   /* Chop it all into chunks that can be digested by hardware: */
   for (py = 0; py < height; py += DY) {
      for (px = 0; px < width; px += DX) {
	 int h = MIN2(DY, height - py);
	 int w = MIN2(DX, width - px);
	 GLuint sz = ALIGN(ALIGN(w,8) * h, 64)/8;
	 GLenum logic_op = ctx->Color.ColorLogicOpEnabled ?
	    ctx->Color.LogicOp : GL_COPY;

	 assert(sz <= sizeof(stipple));
	 memset(stipple, 0, sz);

	 /* May need to adjust this when padding has been introduced in
	  * sz above:
	  *
	  * Have to translate destination coordinates back into source
	  * coordinates.
	  */
         int count = get_bitmap_rect(bitmap_width, bitmap_height, unpack,
                                     bitmap,
                                     -orig_dstx + (dstx + px),
                                     -orig_dsty + y_flip(fb, dsty + py, h),
                                     w, h,
                                     (GLubyte *)stipple,
                                     8,
                                     _mesa_is_winsys_fbo(fb));
         if (count == 0)
	    continue;

	 if (!intelEmitImmediateColorExpandBlit(intel,
						irb->mt->cpp,
						(GLubyte *)stipple,
						sz,
						color,
						irb->mt->region->pitch,
						irb->mt->region->bo,
						0,
						irb->mt->region->tiling,
						dstx + px,
						dsty + py,
						w, h,
						logic_op)) {
	    return false;
	 }

         if (ctx->Query.CurrentOcclusionObject)
            ctx->Query.CurrentOcclusionObject->Result += count;
      }
   }
out:

   if (unlikely(INTEL_DEBUG & DEBUG_SYNC))
      intel_batchbuffer_flush(intel);

   if (_mesa_is_bufferobj(unpack->BufferObj)) {
      /* done with PBO so unmap it now */
      ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj, MAP_INTERNAL);
   }

   intel_check_front_buffer_rendering(intel);

   return true;
}
Esempio n. 30
0
static GLboolean
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)
{
    radeonContextPtr radeon = RADEON_CONTEXT(ctx);
    const struct radeon_renderbuffer *rrb = radeon_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer);
    const gl_format dst_format = gl_format_and_type_to_mesa_format(format, type);
    unsigned dst_rowstride, dst_imagesize, aligned_rowstride, flip_y;
    struct radeon_bo *dst_buffer;
    GLint dst_x = 0, dst_y = 0;
    intptr_t dst_offset;

    /* It's not worth if number of pixels to copy is really small */
    if (width * height < 100) {
        return GL_FALSE;
    }

    if (dst_format == MESA_FORMAT_NONE ||
        !radeon->vtbl.check_blit(dst_format, rrb->pitch / rrb->cpp) || !radeon->vtbl.blit) {
        return GL_FALSE;
    }

    if (ctx->_ImageTransferState || ctx->Color.ColorLogicOpEnabled) {
        return GL_FALSE;
    }

    if (pack->SwapBytes || pack->LsbFirst) {
        return GL_FALSE;
    }

    if (pack->RowLength > 0) {
        dst_rowstride = pack->RowLength;
    } else {
        dst_rowstride = width;
    }

    if (!_mesa_clip_copytexsubimage(ctx, &dst_x, &dst_y, &x, &y, &width, &height)) {
        return GL_TRUE;
    }
    assert(x >= 0 && y >= 0);

    aligned_rowstride = get_texture_image_row_stride(radeon, dst_format, dst_rowstride, 0, GL_TEXTURE_2D);
    dst_rowstride *= _mesa_get_format_bytes(dst_format);
    if (_mesa_is_bufferobj(pack->BufferObj) && aligned_rowstride != dst_rowstride)
        return GL_FALSE;
    dst_imagesize = get_texture_image_size(dst_format,
                                           aligned_rowstride,
                                           height, 1, 0);

    if (!_mesa_is_bufferobj(pack->BufferObj))
    {
        dst_buffer = radeon_bo_open(radeon->radeonScreen->bom, 0, dst_imagesize, 1024, RADEON_GEM_DOMAIN_GTT, 0);
        dst_offset = 0;
    }
    else
    {
        dst_buffer = get_radeon_buffer_object(pack->BufferObj)->bo;
        dst_offset = (intptr_t)pixels;
    }

    /* Disable source Y flipping for FBOs */
    flip_y = _mesa_is_winsys_fbo(ctx->ReadBuffer);
    if (pack->Invert) {
        y = rrb->base.Base.Height - height - y;
        flip_y = !flip_y;
    }

    if (radeon->vtbl.blit(ctx,
                          rrb->bo,
                          rrb->draw_offset,
                          rrb->base.Base.Format,
                          rrb->pitch / rrb->cpp,
                          rrb->base.Base.Width,
                          rrb->base.Base.Height,
                          x,
                          y,
                          dst_buffer,
                          dst_offset,
                          dst_format,
                          aligned_rowstride / _mesa_get_format_bytes(dst_format),
                          width,
                          height,
                          0, /* dst_x */
                          0, /* dst_y */
                          width,
                          height,
                          flip_y))
    {
        if (!_mesa_is_bufferobj(pack->BufferObj))
        {
            radeon_bo_map(dst_buffer, 0);
            copy_rows(pixels, dst_rowstride, dst_buffer->ptr,
                      aligned_rowstride, height, dst_rowstride);
            radeon_bo_unmap(dst_buffer);
            radeon_bo_unref(dst_buffer);
        }

        return GL_TRUE;
    }

    if (!_mesa_is_bufferobj(pack->BufferObj))
        radeon_bo_unref(dst_buffer);

    return GL_FALSE;
}