summaryrefslogtreecommitdiffstats
path: root/src/mesa/drivers/dri/i965/intel_buffers.c
diff options
context:
space:
mode:
authorEric Anholt <anholt@FreeBSD.org>2006-08-09 19:14:05 +0000
committerEric Anholt <anholt@FreeBSD.org>2006-08-09 19:14:05 +0000
commit9f344b3e7d6e23674dd4747faec253f103563b36 (patch)
treee5df3c1ab9a424831d4a4363567a87ff91cc0581 /src/mesa/drivers/dri/i965/intel_buffers.c
parent7b52bed98729a05feab28f6d2b0677e4f84c44c3 (diff)
downloadexternal_mesa3d-9f344b3e7d6e23674dd4747faec253f103563b36.zip
external_mesa3d-9f344b3e7d6e23674dd4747faec253f103563b36.tar.gz
external_mesa3d-9f344b3e7d6e23674dd4747faec253f103563b36.tar.bz2
Add Intel i965G/Q DRI driver.
This driver comes from Tungsten Graphics, with a few further modifications by Intel.
Diffstat (limited to 'src/mesa/drivers/dri/i965/intel_buffers.c')
-rw-r--r--src/mesa/drivers/dri/i965/intel_buffers.c555
1 files changed, 555 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/i965/intel_buffers.c b/src/mesa/drivers/dri/i965/intel_buffers.c
new file mode 100644
index 0000000..8539566
--- /dev/null
+++ b/src/mesa/drivers/dri/i965/intel_buffers.c
@@ -0,0 +1,555 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * 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
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * 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
+ * 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 "intel_screen.h"
+#include "intel_context.h"
+#include "intel_blit.h"
+#include "intel_regions.h"
+#include "intel_batchbuffer.h"
+#include "context.h"
+#include "framebuffer.h"
+#include "macros.h"
+#include "swrast/swrast.h"
+
+GLboolean intel_intersect_cliprects( drm_clip_rect_t *dst,
+ const drm_clip_rect_t *a,
+ const drm_clip_rect_t *b )
+{
+ dst->x1 = MAX2(a->x1, b->x1);
+ dst->x2 = MIN2(a->x2, b->x2);
+ dst->y1 = MAX2(a->y1, b->y1);
+ dst->y2 = MIN2(a->y2, b->y2);
+
+ return (dst->x1 <= dst->x2 &&
+ dst->y1 <= dst->y2);
+}
+
+struct intel_region *intel_drawbuf_region( struct intel_context *intel )
+{
+ switch (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0]) {
+ case BUFFER_BIT_FRONT_LEFT:
+ return intel->front_region;
+ case BUFFER_BIT_BACK_LEFT:
+ return intel->back_region;
+ default:
+ /* Not necessary to fallback - could handle either NONE or
+ * FRONT_AND_BACK cases below.
+ */
+ return NULL;
+ }
+}
+
+struct intel_region *intel_readbuf_region( struct intel_context *intel )
+{
+ GLcontext *ctx = &intel->ctx;
+
+ /* This will have to change to support EXT_fbo's, but is correct
+ * for now:
+ */
+ switch (ctx->ReadBuffer->_ColorReadBufferIndex) {
+ case BUFFER_FRONT_LEFT:
+ return intel->front_region;
+ case BUFFER_BACK_LEFT:
+ return intel->back_region;
+ default:
+ assert(0);
+ return NULL;
+ }
+}
+
+
+
+static void intelBufferSize(GLframebuffer *buffer,
+ GLuint *width,
+ GLuint *height)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct intel_context *intel = intel_context(ctx);
+ /* Need to lock to make sure the driDrawable is uptodate. This
+ * information is used to resize Mesa's software buffers, so it has
+ * to be correct.
+ */
+ LOCK_HARDWARE(intel);
+ if (intel->driDrawable) {
+ *width = intel->driDrawable->w;
+ *height = intel->driDrawable->h;
+ }
+ else {
+ *width = 0;
+ *height = 0;
+ }
+ UNLOCK_HARDWARE(intel);
+}
+
+
+static void intelSetFrontClipRects( struct intel_context *intel )
+{
+ __DRIdrawablePrivate *dPriv = intel->driDrawable;
+
+ if (!dPriv) return;
+
+ intel->numClipRects = dPriv->numClipRects;
+ intel->pClipRects = dPriv->pClipRects;
+ intel->drawX = dPriv->x;
+ intel->drawY = dPriv->y;
+}
+
+
+static void intelSetBackClipRects( struct intel_context *intel )
+{
+ __DRIdrawablePrivate *dPriv = intel->driDrawable;
+
+ if (!dPriv) return;
+
+ if (intel->sarea->pf_enabled == 0 && dPriv->numBackClipRects == 0) {
+ intel->numClipRects = dPriv->numClipRects;
+ intel->pClipRects = dPriv->pClipRects;
+ intel->drawX = dPriv->x;
+ intel->drawY = dPriv->y;
+ } else {
+ intel->numClipRects = dPriv->numBackClipRects;
+ intel->pClipRects = dPriv->pBackClipRects;
+ intel->drawX = dPriv->backX;
+ intel->drawY = dPriv->backY;
+
+ if (dPriv->numBackClipRects == 1 &&
+ dPriv->x == dPriv->backX &&
+ dPriv->y == dPriv->backY) {
+
+ /* Repeat the calculation of the back cliprect dimensions here
+ * as early versions of dri.a in the Xserver are incorrect. Try
+ * very hard not to restrict future versions of dri.a which
+ * might eg. allocate truly private back buffers.
+ */
+ int x1, y1;
+ int x2, y2;
+
+ x1 = dPriv->x;
+ y1 = dPriv->y;
+ x2 = dPriv->x + dPriv->w;
+ y2 = dPriv->y + dPriv->h;
+
+ if (x1 < 0) x1 = 0;
+ if (y1 < 0) y1 = 0;
+ if (x2 > intel->intelScreen->width) x2 = intel->intelScreen->width;
+ if (y2 > intel->intelScreen->height) y2 = intel->intelScreen->height;
+
+ if (x1 == dPriv->pBackClipRects[0].x1 &&
+ y1 == dPriv->pBackClipRects[0].y1) {
+
+ dPriv->pBackClipRects[0].x2 = x2;
+ dPriv->pBackClipRects[0].y2 = y2;
+ }
+ }
+ }
+}
+
+
+void intelWindowMoved( struct intel_context *intel )
+{
+ __DRIdrawablePrivate *dPriv = intel->driDrawable;
+
+ if (!intel->ctx.DrawBuffer) {
+ intelSetFrontClipRects( intel );
+ }
+ else {
+ switch (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0]) {
+ case BUFFER_BIT_FRONT_LEFT:
+ intelSetFrontClipRects( intel );
+ break;
+ case BUFFER_BIT_BACK_LEFT:
+ intelSetBackClipRects( intel );
+ break;
+ default:
+ /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
+ intelSetFrontClipRects( intel );
+ }
+ }
+
+ _mesa_resize_framebuffer(&intel->ctx,
+ (GLframebuffer*)dPriv->driverPrivate,
+ dPriv->w, dPriv->h);
+
+ /* Set state we know depends on drawable parameters:
+ */
+ {
+ GLcontext *ctx = &intel->ctx;
+
+ if (ctx->Driver.Scissor)
+ ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y,
+ ctx->Scissor.Width, ctx->Scissor.Height );
+
+ if (ctx->Driver.DepthRange)
+ ctx->Driver.DepthRange( ctx,
+ ctx->Viewport.Near,
+ ctx->Viewport.Far );
+
+ intel->NewGLState |= _NEW_SCISSOR;
+ }
+}
+
+
+
+/* A true meta version of this would be very simple and additionally
+ * machine independent. Maybe we'll get there one day.
+ */
+static void intelClearWithTris(struct intel_context *intel,
+ GLbitfield mask,
+ GLboolean all,
+ GLint cx, GLint cy,
+ GLint cw, GLint ch)
+{
+ drm_clip_rect_t clear;
+
+ if (INTEL_DEBUG & DEBUG_DRI)
+ _mesa_printf("%s %x\n", __FUNCTION__, mask);
+
+ {
+
+ intel->vtbl.install_meta_state(intel);
+
+ /* Refresh the cx/y/w/h values as they may have been invalidated
+ * by a new window position or size picked up when we did
+ * LOCK_HARDWARE above. The values passed by mesa are not
+ * reliable.
+ */
+ {
+ GLcontext *ctx = &intel->ctx;
+ cx = ctx->DrawBuffer->_Xmin;
+ cy = ctx->DrawBuffer->_Ymin;
+ ch = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
+ cw = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
+ }
+
+ clear.x1 = cx;
+ clear.y1 = cy;
+ clear.x2 = cx + cw;
+ clear.y2 = cy + ch;
+
+ /* Back and stencil cliprects are the same. Try and do both
+ * buffers at once:
+ */
+ if (mask & (BUFFER_BIT_BACK_LEFT|BUFFER_BIT_STENCIL|BUFFER_BIT_DEPTH)) {
+ intel->vtbl.meta_draw_region(intel,
+ intel->back_region,
+ intel->depth_region );
+
+ if (mask & BUFFER_BIT_BACK_LEFT)
+ intel->vtbl.meta_color_mask(intel, GL_TRUE );
+ else
+ intel->vtbl.meta_color_mask(intel, GL_FALSE );
+
+ if (mask & BUFFER_BIT_STENCIL)
+ intel->vtbl.meta_stencil_replace( intel,
+ intel->ctx.Stencil.WriteMask[0],
+ intel->ctx.Stencil.Clear);
+ else
+ intel->vtbl.meta_no_stencil_write(intel);
+
+ if (mask & BUFFER_BIT_DEPTH)
+ intel->vtbl.meta_depth_replace( intel );
+ else
+ intel->vtbl.meta_no_depth_write(intel);
+
+ /* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the
+ * drawing origin may not be correctly emitted.
+ */
+ intel->vtbl.meta_draw_quad(intel,
+ clear.x1, clear.x2,
+ clear.y1, clear.y2,
+ intel->ctx.Depth.Clear,
+ intel->clear_chan[0],
+ intel->clear_chan[1],
+ intel->clear_chan[2],
+ intel->clear_chan[3],
+ 0, 0, 0, 0);
+ }
+
+ /* Front may have different cliprects:
+ */
+ if (mask & BUFFER_BIT_FRONT_LEFT) {
+ intel->vtbl.meta_no_depth_write(intel);
+ intel->vtbl.meta_no_stencil_write(intel);
+ intel->vtbl.meta_color_mask(intel, GL_TRUE );
+ intel->vtbl.meta_draw_region(intel,
+ intel->front_region,
+ intel->depth_region);
+
+ /* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the
+ * drawing origin may not be correctly emitted.
+ */
+ intel->vtbl.meta_draw_quad(intel,
+ clear.x1, clear.x2,
+ clear.y1, clear.y2,
+ 0,
+ intel->clear_chan[0],
+ intel->clear_chan[1],
+ intel->clear_chan[2],
+ intel->clear_chan[3],
+ 0, 0, 0, 0);
+ }
+
+ intel->vtbl.leave_meta_state( intel );
+ }
+}
+
+
+
+
+
+static void intelClear(GLcontext *ctx,
+ GLbitfield mask,
+ GLboolean all,
+ GLint cx, GLint cy,
+ GLint cw, GLint ch)
+{
+ struct intel_context *intel = intel_context( ctx );
+ const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
+ GLbitfield tri_mask = 0;
+ GLbitfield blit_mask = 0;
+ GLbitfield swrast_mask = 0;
+
+ if (INTEL_DEBUG & DEBUG_DRI)
+ fprintf(stderr, "%s %x all %d dims %d,%d %dx%d\n", __FUNCTION__,
+ mask, all, cx, cy, cw, ch);
+
+
+ if (mask & BUFFER_BIT_FRONT_LEFT) {
+ if (colorMask == ~0) {
+ blit_mask |= BUFFER_BIT_FRONT_LEFT;
+ }
+ else {
+ tri_mask |= BUFFER_BIT_FRONT_LEFT;
+ }
+ }
+
+ if (mask & BUFFER_BIT_BACK_LEFT) {
+ if (colorMask == ~0) {
+ blit_mask |= BUFFER_BIT_BACK_LEFT;
+ }
+ else {
+ tri_mask |= BUFFER_BIT_BACK_LEFT;
+ }
+ }
+
+
+ if (mask & BUFFER_BIT_STENCIL) {
+ if (!intel->hw_stencil) {
+ swrast_mask |= BUFFER_BIT_STENCIL;
+ }
+ else if ((ctx->Stencil.WriteMask[0] & 0xff) != 0xff ||
+ intel->depth_region->tiled) {
+ tri_mask |= BUFFER_BIT_STENCIL;
+ }
+ else {
+ blit_mask |= BUFFER_BIT_STENCIL;
+ }
+ }
+
+ /* Do depth with stencil if possible to avoid 2nd pass over the
+ * same buffer.
+ */
+ if (mask & BUFFER_BIT_DEPTH) {
+ if ((tri_mask & BUFFER_BIT_STENCIL) ||
+ intel->depth_region->tiled)
+ tri_mask |= BUFFER_BIT_DEPTH;
+ else
+ blit_mask |= BUFFER_BIT_DEPTH;
+ }
+
+ swrast_mask |= (mask & BUFFER_BIT_ACCUM);
+
+ intelFlush( ctx );
+
+ if (blit_mask)
+ intelClearWithBlit( ctx, blit_mask, all, cx, cy, cw, ch );
+
+ if (tri_mask)
+ intelClearWithTris( intel, tri_mask, all, cx, cy, cw, ch);
+
+ if (swrast_mask)
+ _swrast_Clear( ctx, swrast_mask, all, cx, cy, cw, ch );
+}
+
+
+
+
+
+
+
+/* Flip the front & back buffers
+ */
+static void intelPageFlip( const __DRIdrawablePrivate *dPriv )
+{
+#if 0
+ struct intel_context *intel;
+ int tmp, ret;
+
+ if (INTEL_DEBUG & DEBUG_IOCTL)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+ assert(dPriv);
+ assert(dPriv->driContextPriv);
+ assert(dPriv->driContextPriv->driverPrivate);
+
+ intel = (struct intel_context *) dPriv->driContextPriv->driverPrivate;
+
+ intelFlush( &intel->ctx );
+ LOCK_HARDWARE( intel );
+
+ if (dPriv->pClipRects) {
+ *(drm_clip_rect_t *)intel->sarea->boxes = dPriv->pClipRects[0];
+ intel->sarea->nbox = 1;
+ }
+
+ ret = drmCommandNone(intel->driFd, DRM_I830_FLIP);
+ if (ret) {
+ fprintf(stderr, "%s: %d\n", __FUNCTION__, ret);
+ UNLOCK_HARDWARE( intel );
+ exit(1);
+ }
+
+ tmp = intel->sarea->last_enqueue;
+ intelRefillBatchLocked( intel );
+ UNLOCK_HARDWARE( intel );
+
+
+ intelSetDrawBuffer( &intel->ctx, intel->ctx.Color.DriverDrawBuffer );
+#endif
+}
+
+
+void intelSwapBuffers( __DRIdrawablePrivate *dPriv )
+{
+ if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
+ struct intel_context *intel;
+ GLcontext *ctx;
+ intel = (struct intel_context *) dPriv->driContextPriv->driverPrivate;
+ ctx = &intel->ctx;
+ if (ctx->Visual.doubleBufferMode) {
+ _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
+ if ( 0 /*intel->doPageFlip*/ ) { /* doPageFlip is never set !!! */
+ intelPageFlip( dPriv );
+ } else {
+ intelCopyBuffer( dPriv, NULL );
+ }
+ if (intel->aub_file) {
+ intelFlush(ctx);
+ intel->vtbl.aub_dump_bmp( intel, 1 );
+
+ intel->aub_wrap = 1;
+ }
+ }
+ } else {
+ /* XXX this shouldn't be an error but we can't handle it for now */
+ fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__);
+ }
+}
+
+void intelCopySubBuffer( __DRIdrawablePrivate *dPriv,
+ int x, int y, int w, int h )
+{
+ if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
+ struct intel_context *intel = dPriv->driContextPriv->driverPrivate;
+ GLcontext *ctx = &intel->ctx;
+
+ if (ctx->Visual.doubleBufferMode) {
+ drm_clip_rect_t rect;
+ rect.x1 = x + dPriv->x;
+ rect.y1 = (dPriv->h - y - h) + dPriv->y;
+ rect.x2 = rect.x1 + w;
+ rect.y2 = rect.y1 + h;
+ _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
+ intelCopyBuffer( dPriv, &rect );
+ }
+ } else {
+ /* XXX this shouldn't be an error but we can't handle it for now */
+ fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__);
+ }
+}
+
+
+static void intelDrawBuffer(GLcontext *ctx, GLenum mode )
+{
+ struct intel_context *intel = intel_context(ctx);
+ int front = 0;
+
+ if (!ctx->DrawBuffer)
+ return;
+
+ switch ( ctx->DrawBuffer->_ColorDrawBufferMask[0] ) {
+ case BUFFER_BIT_FRONT_LEFT:
+ front = 1;
+ FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE );
+ break;
+ case BUFFER_BIT_BACK_LEFT:
+ front = 0;
+ FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE );
+ break;
+ default:
+ FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE );
+ return;
+ }
+
+ if ( intel->sarea->pf_current_page == 1 )
+ front ^= 1;
+
+ intelSetFrontClipRects( intel );
+
+
+ if (front) {
+ if (intel->draw_region != intel->front_region) {
+ intel_region_release(intel, &intel->draw_region);
+ intel_region_reference(&intel->draw_region, intel->front_region);
+ }
+ } else {
+ if (intel->draw_region != intel->back_region) {
+ intel_region_release(intel, &intel->draw_region);
+ intel_region_reference(&intel->draw_region, intel->back_region);
+ }
+ }
+
+ intel->vtbl.set_draw_region( intel,
+ intel->draw_region,
+ intel->depth_region);
+}
+
+static void intelReadBuffer( GLcontext *ctx, GLenum mode )
+{
+ /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
+}
+
+
+
+void intelInitBufferFuncs( struct dd_function_table *functions )
+{
+ functions->Clear = intelClear;
+ functions->GetBufferSize = intelBufferSize;
+ functions->ResizeBuffers = _mesa_resize_framebuffer;
+ functions->DrawBuffer = intelDrawBuffer;
+ functions->ReadBuffer = intelReadBuffer;
+}