new files from merge of texmem driver

This commit is contained in:
Keith Whitwell 2006-08-02 10:08:58 +00:00
parent 527c05eb2a
commit ded29089f3
22 changed files with 5396 additions and 0 deletions

View file

@ -0,0 +1,62 @@
/**************************************************************************
*
* 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.
*
**************************************************************************/
#ifndef INTEL_BLIT_H
#define INTEL_BLIT_H
#include "intel_context.h"
#include "intel_ioctl.h"
extern void intelCopyBuffer( const __DRIdrawablePrivate *dpriv,
const drm_clip_rect_t *rect);
extern void intelClearWithBlit(GLcontext *ctx, GLbitfield mask, GLboolean all,
GLint cx1, GLint cy1, GLint cw, GLint ch);
extern void intelEmitCopyBlit( struct intel_context *intel,
GLuint cpp,
GLshort src_pitch,
GLuint src_buffer,
GLuint src_offset,
GLshort dst_pitch,
GLuint dst_buffer,
GLuint dst_offset,
GLshort srcx, GLshort srcy,
GLshort dstx, GLshort dsty,
GLshort w, GLshort h );
extern void intelEmitFillBlit( struct intel_context *intel,
GLuint cpp,
GLshort dst_pitch,
GLuint dst_buffer,
GLuint dst_offset,
GLshort x, GLshort y,
GLshort w, GLshort h,
GLuint color );
#endif

View file

@ -0,0 +1,201 @@
/**************************************************************************
*
* 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 "imports.h"
#include "mtypes.h"
#include "bufferobj.h"
#include "intel_context.h"
#include "intel_buffer_objects.h"
#include "intel_bufmgr.h"
/**
* There is some duplication between mesa's bufferobjects and our
* bufmgr buffers. Both have an integer handle and a hashtable to
* lookup an opaque structure. It would be nice if the handles and
* internal structure where somehow shared.
*/
static struct gl_buffer_object *intel_bufferobj_alloc( GLcontext *ctx,
GLuint name,
GLenum target )
{
struct intel_context *intel = intel_context(ctx);
struct intel_buffer_object *obj = MALLOC_STRUCT(intel_buffer_object);
_mesa_initialize_buffer_object(&obj->Base, name, target);
/* XXX: We generate our own handle, which is different to 'name' above.
*/
bmGenBuffers(intel->bm, 1, &obj->buffer, 0);
return &obj->Base;
}
/**
* Deallocate/free a vertex/pixel buffer object.
* Called via glDeleteBuffersARB().
*/
static void intel_bufferobj_free( GLcontext *ctx,
struct gl_buffer_object *obj )
{
struct intel_context *intel = intel_context(ctx);
struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
assert(intel_obj);
if (intel_obj->buffer)
bmDeleteBuffers( intel->bm, 1, &intel_obj->buffer );
_mesa_free(intel_obj);
}
/**
* Allocate space for and store data in a buffer object. Any data that was
* previously stored in the buffer object is lost. If data is NULL,
* memory will be allocated, but no copy will occur.
* Called via glBufferDataARB().
*/
static void intel_bufferobj_data( GLcontext *ctx,
GLenum target,
GLsizeiptrARB size,
const GLvoid *data,
GLenum usage,
struct gl_buffer_object *obj )
{
struct intel_context *intel = intel_context(ctx);
struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
/* XXX: do something useful with 'usage' (eg. populate flags
* argument below)
*/
assert(intel_obj);
obj->Size = size;
obj->Usage = usage;
bmBufferData(intel->bm, intel_obj->buffer, size, data, 0);
}
/**
* Replace data in a subrange of buffer object. If the data range
* specified by size + offset extends beyond the end of the buffer or
* if data is NULL, no copy is performed.
* Called via glBufferSubDataARB().
*/
static void intel_bufferobj_subdata( GLcontext *ctx,
GLenum target,
GLintptrARB offset,
GLsizeiptrARB size,
const GLvoid * data,
struct gl_buffer_object * obj )
{
struct intel_context *intel = intel_context(ctx);
struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
assert(intel_obj);
bmBufferSubData(intel->bm, intel_obj->buffer, offset, size, data);
}
/**
* Called via glGetBufferSubDataARB().
*/
static void intel_bufferobj_get_subdata( GLcontext *ctx,
GLenum target,
GLintptrARB offset,
GLsizeiptrARB size,
GLvoid * data,
struct gl_buffer_object * obj )
{
struct intel_context *intel = intel_context(ctx);
struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
assert(intel_obj);
bmBufferGetSubData(intel->bm, intel_obj->buffer, offset, size, data);
}
/**
* Called via glMapBufferARB().
*/
static void *intel_bufferobj_map( GLcontext *ctx,
GLenum target,
GLenum access,
struct gl_buffer_object *obj )
{
struct intel_context *intel = intel_context(ctx);
struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
/* XXX: Translate access to flags arg below:
*/
assert(intel_obj);
obj->Pointer = bmMapBuffer(intel->bm, intel_obj->buffer, 0);
return obj->Pointer;
}
/**
* Called via glMapBufferARB().
*/
static GLboolean intel_bufferobj_unmap( GLcontext *ctx,
GLenum target,
struct gl_buffer_object *obj )
{
struct intel_context *intel = intel_context(ctx);
struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
assert(intel_obj);
assert(obj->Pointer);
bmUnmapBuffer(intel->bm, intel_obj->buffer);
obj->Pointer = NULL;
return GL_TRUE;
}
GLuint intel_bufferobj_buffer( const struct intel_buffer_object *intel_obj )
{
return intel_obj->buffer;
}
void intel_bufferobj_init( struct intel_context *intel )
{
GLcontext *ctx = &intel->ctx;
ctx->Driver.NewBufferObject = intel_bufferobj_alloc;
ctx->Driver.DeleteBuffer = intel_bufferobj_free;
ctx->Driver.BufferData = intel_bufferobj_data;
ctx->Driver.BufferSubData = intel_bufferobj_subdata;
ctx->Driver.GetBufferSubData = intel_bufferobj_get_subdata;
ctx->Driver.MapBuffer = intel_bufferobj_map;
ctx->Driver.UnmapBuffer = intel_bufferobj_unmap;
}

View file

@ -0,0 +1,70 @@
/**************************************************************************
*
* Copyright 2005 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.
*
**************************************************************************/
#ifndef INTEL_BUFFEROBJ_H
#define INTEL_BUFFEROBJ_H
#include "mtypes.h"
struct intel_context;
struct gl_buffer_object;
/**
* Intel vertex/pixel buffer object, derived from Mesa's gl_buffer_object.
*/
struct intel_buffer_object {
struct gl_buffer_object Base;
GLuint buffer; /* the low-level buffer manager's buffer handle */
};
/* Get the bm buffer associated with a GL bufferobject:
*/
GLuint intel_bufferobj_buffer( const struct intel_buffer_object *obj );
/* Hook the bufferobject implementation into mesa:
*/
void intel_bufferobj_init( struct intel_context *intel );
/* Are the obj->Name tests necessary? Unfortunately yes, mesa
* allocates a couple of gl_buffer_object structs statically, and
* the Name == 0 test is the only way to identify them and avoid
* casting them erroneously to our structs.
*/
static INLINE struct intel_buffer_object *
intel_buffer_object( struct gl_buffer_object *obj )
{
if (obj->Name)
return (struct intel_buffer_object *)obj;
else
return NULL;
}
#endif

View file

@ -0,0 +1,947 @@
/**************************************************************************
*
* 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_buffers.h"
#include "intel_depthstencil.h"
#include "intel_fbo.h"
#include "intel_tris.h"
#include "intel_regions.h"
#include "intel_batchbuffer.h"
#include "context.h"
#include "framebuffer.h"
#include "swrast/swrast.h"
/**
* XXX move this into a new dri/common/cliprects.c file.
*/
GLboolean intel_intersect_cliprects( drm_clip_rect_t *dst,
const drm_clip_rect_t *a,
const drm_clip_rect_t *b )
{
GLint bx = b->x1;
GLint by = b->y1;
GLint bw = b->x2 - bx;
GLint bh = b->y2 - by;
if (bx < a->x1) bw -= a->x1 - bx, bx = a->x1;
if (by < a->y1) bh -= a->y1 - by, by = a->y1;
if (bx + bw > a->x2) bw = a->x2 - bx;
if (by + bh > a->y2) bh = a->y2 - by;
if (bw <= 0) return GL_FALSE;
if (bh <= 0) return GL_FALSE;
dst->x1 = bx;
dst->y1 = by;
dst->x2 = bx + bw;
dst->y2 = by + bh;
return GL_TRUE;
}
/**
* Return pointer to current color drawing region, or NULL.
*/
struct intel_region *intel_drawbuf_region( struct intel_context *intel )
{
struct intel_renderbuffer *irbColor =
intel_renderbuffer(intel->ctx.DrawBuffer->_ColorDrawBuffers[0][0]);
if (irbColor)
return irbColor->region;
else
return NULL;
}
/**
* Return pointer to current color reading region, or NULL.
*/
struct intel_region *intel_readbuf_region( struct intel_context *intel )
{
struct intel_renderbuffer *irb
= intel_renderbuffer(intel->ctx.ReadBuffer->_ColorReadBuffer);
if (irb)
return irb->region;
else
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.
*/
/* XXX This isn't 100% correct, the given buffer might not be
* bound to the current context!
*/
LOCK_HARDWARE(intel);
if (intel->driDrawable) {
*width = intel->driDrawable->w;
*height = intel->driDrawable->h;
}
else {
*width = 0;
*height = 0;
}
UNLOCK_HARDWARE(intel);
}
/**
* Update the following fields for rendering to a user-created FBO:
* intel->numClipRects
* intel->pClipRects
* intel->drawX
* intel->drawY
*/
static void intelSetRenderbufferClipRects( struct intel_context *intel )
{
assert(intel->ctx.DrawBuffer->Width > 0);
assert(intel->ctx.DrawBuffer->Height > 0);
intel->fboRect.x1 = 0;
intel->fboRect.y1 = 0;
intel->fboRect.x2 = intel->ctx.DrawBuffer->Width;
intel->fboRect.y2 = intel->ctx.DrawBuffer->Height;
intel->numClipRects = 1;
intel->pClipRects = &intel->fboRect;
intel->drawX = 0;
intel->drawY = 0;
}
/**
* As above, but for rendering to front buffer of a window.
* \sa intelSetRenderbufferClipRects
*/
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;
}
/**
* As above, but for rendering to back buffer of a window.
*/
static void intelSetBackClipRects( struct intel_context *intel )
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
if (!dPriv) return;
if (intel->sarea->pf_enabled == 0 && dPriv->numBackClipRects == 0) {
/* use the front clip rects */
intel->numClipRects = dPriv->numClipRects;
intel->pClipRects = dPriv->pClipRects;
intel->drawX = dPriv->x;
intel->drawY = dPriv->y;
} else {
/* use the back clip rects */
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;
}
}
}
}
/**
* This will be called whenever the currently bound window is moved/resized.
* XXX: actually, it seems to NOT be called when the window is only moved (BP).
*/
void intelWindowMoved( struct intel_context *intel )
{
GLcontext *ctx = &intel->ctx;
if (!intel->ctx.DrawBuffer) {
/* when would this happen? -BP */
intelSetFrontClipRects( intel );
}
else if (intel->ctx.DrawBuffer->Name != 0) {
/* drawing to user-created FBO - do nothing */
/* Cliprects would be set from intelDrawBuffer() */
}
else {
/* drawing to a window */
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 );
}
}
/* this update Mesa's notion of window size */
if (ctx->WinSysDrawBuffer) {
_mesa_resize_framebuffer(ctx, ctx->WinSysDrawBuffer,
intel->driDrawable->w, intel->driDrawable->h);
}
/* Update hardware scissor */
ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y,
ctx->Scissor.Width, ctx->Scissor.Height );
}
/* 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)
{
GLcontext *ctx = &intel->ctx;
drm_clip_rect_t clear;
if (INTEL_DEBUG & DEBUG_DRI)
_mesa_printf("%s 0x%x\n", __FUNCTION__, mask);
LOCK_HARDWARE(intel);
/* XXX FBO: was: intel->driDrawable->numClipRects */
if (intel->numClipRects) {
GLuint buf;
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.
*/
{
cx = ctx->DrawBuffer->_Xmin;
cy = ctx->DrawBuffer->_Ymin;
ch = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
cw = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
}
/* note: regardless of 'all', cx, cy, cw, ch are now correct */
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)) {
struct intel_region *backRegion
= intel_get_rb_region(ctx->DrawBuffer, BUFFER_BACK_LEFT);
struct intel_region *depthRegion
= intel_get_rb_region(ctx->DrawBuffer, BUFFER_DEPTH);
const GLuint clearColor = (backRegion && backRegion->cpp == 4)
? intel->ClearColor8888 : intel->ClearColor565;
intel->vtbl.meta_draw_region(intel, backRegion, depthRegion );
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_meta_draw_quad(intel,
clear.x1, clear.x2,
clear.y1, clear.y2,
intel->ctx.Depth.Clear,
clearColor,
0, 0, 0, 0); /* texcoords */
mask &= ~(BUFFER_BIT_BACK_LEFT|BUFFER_BIT_STENCIL|BUFFER_BIT_DEPTH);
}
/* clear the remaining (color) renderbuffers */
for (buf = 0; buf < BUFFER_COUNT && mask; buf++) {
const GLuint bufBit = 1 << buf;
if (mask & bufBit) {
struct intel_renderbuffer *irbColor =
intel_renderbuffer(ctx->DrawBuffer->
Attachment[buf].Renderbuffer);
GLuint color = (irbColor->region->cpp == 4)
? intel->ClearColor8888 : intel->ClearColor565;
ASSERT(irbColor);
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, irbColor->region, NULL);
/* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the
* drawing origin may not be correctly emitted.
*/
intel_meta_draw_quad(intel,
clear.x1, clear.x2,
clear.y1, clear.y2,
0, /* depth clear val */
color,
0, 0, 0, 0); /* texcoords */
mask &= ~bufBit;
}
}
intel->vtbl.leave_meta_state( intel );
intel_batchbuffer_flush( intel->batch );
}
UNLOCK_HARDWARE(intel);
}
/**
* Copy the window contents named by dPriv to the rotated (or reflected)
* color buffer.
* srcBuf is BUFFER_BIT_FRONT_LEFT or BUFFER_BIT_BACK_LEFT to indicate the source.
*/
void intelRotateWindow(struct intel_context *intel,
__DRIdrawablePrivate *dPriv,
GLuint srcBuf)
{
intelScreenPrivate *screen = intel->intelScreen;
const GLuint cpp = screen->cpp;
drm_clip_rect_t fullRect;
GLuint srcOffset, srcPitch;
const drm_clip_rect_t *clipRects;
int numClipRects;
int i;
GLenum format, type;
int xOrig, yOrig;
int origNumClipRects;
drm_clip_rect_t *origRects;
/*
* set up hardware state
*/
intelFlush( &intel->ctx );
LOCK_HARDWARE(intel);
if (!intel->numClipRects) {
UNLOCK_HARDWARE(intel);
return;
}
intel->vtbl.install_meta_state(intel);
intel->vtbl.meta_no_depth_write( intel );
intel->vtbl.meta_no_stencil_write( intel );
intel->vtbl.meta_color_mask( intel, GL_FALSE );
/* save current drawing origin and cliprects (restored at end) */
xOrig = intel->drawX;
yOrig = intel->drawY;
origNumClipRects = intel->numClipRects;
origRects = intel->pClipRects;
/*
* set drawing origin, cliprects for full-screen access to rotated screen
*/
fullRect.x1 = 0;
fullRect.y1 = 0;
fullRect.x2 = screen->rotatedWidth;
fullRect.y2 = screen->rotatedHeight;
intel->drawX = 0;
intel->drawY = 0;
intel->numClipRects = 1;
intel->pClipRects = &fullRect;
intel->vtbl.meta_draw_region( intel,
intel->rotated_region,
NULL ); /* ? */
if (cpp == 4) {
format = GL_BGRA;
type = GL_UNSIGNED_BYTE;
}
else {
format = GL_BGR;
type = GL_UNSIGNED_SHORT_5_6_5_REV;
}
if (srcBuf == BUFFER_BIT_FRONT_LEFT) {
srcPitch = screen->front.pitch; /* in bytes */
srcOffset = screen->front.offset; /* bytes */
clipRects = dPriv->pClipRects;
numClipRects = dPriv->numClipRects;
}
else {
srcPitch = screen->back.pitch; /* in bytes */
srcOffset = screen->back.offset; /* bytes */
clipRects = dPriv->pBackClipRects;
numClipRects = dPriv->numBackClipRects;
}
/* set the whole screen up as a texture to avoid alignment issues */
intel->vtbl.meta_tex_rect_source(intel,
srcOffset, /* XXX */
screen->width,
screen->height,
srcPitch,
format,
type);
intel->vtbl.meta_texture_blend_replace(intel);
/*
* loop over the source window's cliprects
*/
for (i = 0; i < numClipRects; i++) {
int srcX0 = clipRects[i].x1;
int srcY0 = clipRects[i].y1;
int srcX1 = clipRects[i].x2;
int srcY1 = clipRects[i].y2;
GLfloat verts[4][2], tex[4][2];
int j;
/* build vertices for four corners of clip rect */
verts[0][0] = srcX0; verts[0][1] = srcY0;
verts[1][0] = srcX1; verts[1][1] = srcY0;
verts[2][0] = srcX1; verts[2][1] = srcY1;
verts[3][0] = srcX0; verts[3][1] = srcY1;
/* .. and texcoords */
tex[0][0] = srcX0; tex[0][1] = srcY0;
tex[1][0] = srcX1; tex[1][1] = srcY0;
tex[2][0] = srcX1; tex[2][1] = srcY1;
tex[3][0] = srcX0; tex[3][1] = srcY1;
/* transform coords to rotated screen coords */
for (j = 0; j < 4; j++) {
matrix23TransformCoordf(&screen->rotMatrix,
&verts[j][0], &verts[j][1]);
}
/* draw polygon to map source image to dest region */
intel_meta_draw_poly(intel, 4, verts, 0, 0, tex);
} /* cliprect loop */
intel->vtbl.leave_meta_state( intel );
intel_batchbuffer_flush( intel->batch );
/* restore original drawing origin and cliprects */
intel->drawX = xOrig;
intel->drawY = yOrig;
intel->numClipRects = origNumClipRects;
intel->pClipRects = origRects;
UNLOCK_HARDWARE(intel);
}
/**
* Called by ctx->Driver.Clear.
*/
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;
GLuint i;
if (0)
fprintf(stderr, "%s\n", __FUNCTION__);
/* HW color buffers (front, back, aux, generic FBO, etc) */
if (colorMask == ~0) {
/* clear all R,G,B,A */
/* XXX FBO: need to check if colorbuffers are software RBOs! */
blit_mask |= (mask & BUFFER_BITS_COLOR);
}
else {
/* glColorMask in effect */
tri_mask |= (mask & BUFFER_BITS_COLOR);
}
/* HW stencil */
if (mask & BUFFER_BIT_STENCIL) {
const struct intel_region *stencilRegion
= intel_get_rb_region(ctx->DrawBuffer, BUFFER_STENCIL);
if (stencilRegion) {
/* have hw stencil */
if ((ctx->Stencil.WriteMask[0] & 0xff) != 0xff) {
/* not clearing all stencil bits, so use triangle clearing */
tri_mask |= BUFFER_BIT_STENCIL;
}
else {
/* clearing all stencil bits, use blitting */
blit_mask |= BUFFER_BIT_STENCIL;
}
}
}
/* HW depth */
if (mask & BUFFER_BIT_DEPTH) {
/* clear depth with whatever method is used for stencil (see above) */
if (tri_mask & BUFFER_BIT_STENCIL)
tri_mask |= BUFFER_BIT_DEPTH;
else
blit_mask |= BUFFER_BIT_DEPTH;
}
/* SW fallback clearing */
swrast_mask = mask & ~tri_mask & ~blit_mask;
for (i = 0; i < BUFFER_COUNT; i++) {
GLuint bufBit = 1 << i;
if ((blit_mask | tri_mask) & bufBit) {
if (!ctx->DrawBuffer->Attachment[i].Renderbuffer->ClassID) {
blit_mask &= ~bufBit;
tri_mask &= ~bufBit;
swrast_mask |= bufBit;
}
}
}
intelFlush( ctx ); /* XXX intelClearWithBlit also does this */
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
}
#if 0
void intelSwapBuffers( __DRIdrawablePrivate *dPriv )
{
if (dPriv->driverPrivate) {
const struct gl_framebuffer *fb
= (struct gl_framebuffer *) dPriv->driverPrivate;
if (fb->Visual.doubleBufferMode) {
GET_CURRENT_CONTEXT(ctx);
if (ctx && ctx->DrawBuffer == fb) {
_mesa_notifySwapBuffers( ctx ); /* flush pending rendering */
}
if ( 0 /*intel->doPageFlip*/ ) { /* doPageFlip is never set !!! */
intelPageFlip( dPriv );
} else {
intelCopyBuffer( dPriv );
}
}
}
else {
_mesa_problem(NULL,
"dPriv has no gl_framebuffer pointer in intelSwapBuffers");
}
}
#else
/* Trunk version:
*/
void intelSwapBuffers( __DRIdrawablePrivate *dPriv )
{
if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
struct intel_context *intel =
(struct intel_context *) dPriv->driContextPriv->driverPrivate;
GLcontext *ctx = &intel->ctx;
if (ctx->Visual.doubleBufferMode) {
intelScreenPrivate *screen = intel->intelScreen;
_mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
if ( 0 /*intel->doPageFlip*/ ) { /* doPageFlip is never set !!! */
intelPageFlip( dPriv );
} else {
intelCopyBuffer( dPriv, NULL );
}
if (screen->current_rotation != 0) {
intelRotateWindow(intel, dPriv, BUFFER_BIT_FRONT_LEFT);
}
}
} 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__);
}
}
#endif
void intelCopySubBuffer( __DRIdrawablePrivate *dPriv,
int x, int y, int w, int h )
{
if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
struct intel_context *intel =
(struct intel_context *) 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__);
}
}
/**
* Update the hardware state for drawing into a window or framebuffer object.
*
* Called by glDrawBuffer, glBindFramebufferEXT, MakeCurrent, and other
* places within the driver.
*
* Basically, this needs to be called any time the current framebuffer
* changes, the renderbuffers change, or we need to draw into different
* color buffers.
*/
void
intel_draw_buffer(GLcontext *ctx, struct gl_framebuffer *fb)
{
struct intel_context *intel = intel_context(ctx);
struct intel_region *colorRegion, *depthRegion = NULL;
struct intel_renderbuffer *irbDepth = NULL, *irbStencil = NULL;
int front = 0; /* drawing to front color buffer? */
if (!fb) {
/* this can happen during the initial context initialization */
return;
}
/* Do this here, note core Mesa, since this function is called from
* many places within the driver.
*/
if (ctx->NewState & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
/* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */
_mesa_update_framebuffer(ctx);
/* this updates the DrawBuffer's Width/Height if it's a FBO */
_mesa_update_draw_buffer_bounds(ctx);
}
if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
/* this may occur when we're called by glBindFrameBuffer() during
* the process of someone setting up renderbuffers, etc.
*/
/*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/
return;
}
if (fb->Name)
intel_validate_paired_depth_stencil(ctx, fb);
/*
* How many color buffers are we drawing into?
*/
if (fb->_NumColorDrawBuffers[0] != 1
#if 0
/* XXX FBO temporary - always use software rendering */
|| 1
#endif
) {
/* writing to 0 or 2 or 4 color buffers */
/*_mesa_debug(ctx, "Software rendering\n");*/
FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE );
front = 1; /* might not have back color buffer */
}
else {
/* draw to exactly one color buffer */
/*_mesa_debug(ctx, "Hardware rendering\n");*/
FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE );
if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT) {
front = 1;
}
}
/*
* Get the intel_renderbuffer for the colorbuffer we're drawing into.
* And set up cliprects.
*/
if (fb->Name == 0) {
/* drawing to window system buffer */
if (intel->sarea->pf_current_page == 1 ) {
/* page flipped back/front */
front ^= 1;
}
if (front) {
intelSetFrontClipRects( intel );
colorRegion = intel_get_rb_region(fb, BUFFER_FRONT_LEFT);
}
else {
intelSetBackClipRects( intel );
colorRegion = intel_get_rb_region(fb, BUFFER_BACK_LEFT);
}
}
else {
/* drawing to user-created FBO */
struct intel_renderbuffer *irb;
intelSetRenderbufferClipRects(intel);
irb = intel_renderbuffer(fb->_ColorDrawBuffers[0][0]);
colorRegion = (irb && irb->region) ? irb->region : NULL;
}
/* Update culling direction which changes depending on the
* orientation of the buffer:
*/
if (ctx->Driver.FrontFace)
ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace);
else
ctx->NewState |= _NEW_POLYGON;
if (!colorRegion) {
FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE );
}
else {
FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE );
}
/***
*** Get depth buffer region and check if we need a software fallback.
*** Note that the depth buffer is usually a DEPTH_STENCIL buffer.
***/
if (fb->_DepthBuffer && fb->_DepthBuffer->Wrapped) {
irbDepth = intel_renderbuffer(fb->_DepthBuffer->Wrapped);
if (irbDepth->region) {
FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE);
depthRegion = irbDepth->region;
}
else {
FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_TRUE);
depthRegion = NULL;
}
}
else {
/* not using depth buffer */
FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE);
depthRegion = NULL;
}
/***
*** Stencil buffer
*** This can only be hardware accelerated if we're using a
*** combined DEPTH_STENCIL buffer (for now anyway).
***/
if (fb->_StencilBuffer && fb->_StencilBuffer->Wrapped) {
irbStencil = intel_renderbuffer(fb->_StencilBuffer->Wrapped);
if (irbStencil && irbStencil->region) {
ASSERT(irbStencil->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE);
/* need to re-compute stencil hw state */
ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled);
if (!depthRegion)
depthRegion = irbStencil->region;
}
else {
FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_TRUE);
}
}
else {
/* XXX FBO: instead of FALSE, pass ctx->Stencil.Enabled ??? */
FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE);
/* need to re-compute stencil hw state */
ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled);
}
/**
** Release old regions, reference new regions
**/
#if 0 /* XXX FBO: this seems to be redundant with i915_state_draw_region() */
if (intel->draw_region != colorRegion) {
intel_region_release(intel, &intel->draw_region);
intel_region_reference(&intel->draw_region, colorRegion);
}
if (intel->depth_region != depthRegion) {
intel_region_release(intel, &intel->depth_region);
intel_region_reference(&intel->depth_region, depthRegion);
}
#endif
intel->vtbl.set_draw_region( intel, colorRegion, depthRegion );
/* update viewport since it depends on window size */
ctx->Driver.Viewport(ctx, ctx->Viewport.X, ctx->Viewport.Y,
ctx->Viewport.Width, ctx->Viewport.Height);
/* Update hardware scissor */
ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y,
ctx->Scissor.Width, ctx->Scissor.Height );
}
static void
intelDrawBuffer(GLcontext *ctx, GLenum mode)
{
intel_draw_buffer(ctx, ctx->DrawBuffer);
}
static void
intelReadBuffer( GLcontext *ctx, GLenum mode )
{
if (ctx->ReadBuffer == ctx->DrawBuffer) {
/* This will update FBO completeness status.
* A framebuffer will be incomplete if the GL_READ_BUFFER setting
* refers to a missing renderbuffer. Calling glReadBuffer can set
* that straight and can make the drawing buffer complete.
*/
intel_draw_buffer(ctx, ctx->DrawBuffer);
}
/* Generally, functions which read pixels (glReadPixels, glCopyPixels, etc)
* reference ctx->ReadBuffer and do appropriate state checks.
*/
}
void intelInitBufferFuncs( struct dd_function_table *functions )
{
functions->Clear = intelClear;
functions->GetBufferSize = intelBufferSize;
functions->ResizeBuffers = _mesa_resize_framebuffer;
functions->DrawBuffer = intelDrawBuffer;
functions->ReadBuffer = intelReadBuffer;
}

View file

@ -0,0 +1,63 @@
/**************************************************************************
*
* Copyright 2006 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.
*
**************************************************************************/
#ifndef INTEL_BUFFERS_H
#define INTEL_BUFFERS_H
struct intel_context;
extern GLboolean
intel_intersect_cliprects(drm_clip_rect_t *dest,
const drm_clip_rect_t *a,
const drm_clip_rect_t *b);
extern struct intel_region *
intel_readbuf_region(struct intel_context *intel);
extern struct intel_region *
intel_drawbuf_region(struct intel_context *intel);
extern void
intelSwapBuffers( __DRIdrawablePrivate *dPriv);
extern void
intelWindowMoved(struct intel_context *intel);
extern void
intel_draw_buffer(GLcontext *ctx, struct gl_framebuffer *fb);
extern void
intelInitBufferFuncs(struct dd_function_table *functions);
extern void
intelRotateWindow(struct intel_context *intel,
__DRIdrawablePrivate *dPriv,
GLuint srcBuf);
#endif /* INTEL_BUFFERS_H */

View file

@ -0,0 +1,132 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Steamboat Springs, CO.
* 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 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
* THE COPYRIGHT HOLDERS, AUTHORS 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.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
*
**************************************************************************/
#ifndef BUFMGR_H
#define BUFMGR_H
#include "intel_context.h"
/* Note that this is destined to be external to Mesa, so don't use GL
* types like GLuint, etc.
*/
/* The buffer manager context. Opaque.
*/
struct bufmgr;
struct bufmgr *bm_intel_Attach(struct intel_context *intel);
#define BM_BATCHBUFFER 0x10000000 /* for map - pointer will be accessed
* without dri lock */
/* Stick closely to ARB_vbo semantics - they're well defined and
* understood, and drivers can just pass the calls through without too
* much thunking.
*/
void bmGenBuffers(struct bufmgr *, unsigned n, unsigned *buffers,
unsigned flags);
void bmDeleteBuffers(struct bufmgr *, unsigned n, unsigned *buffers);
/* The driver has more intimate knowledge of the hardare than a GL
* client would, so flags here is more proscriptive than the usage
* values in the ARB_vbo interface:
*/
void bmBufferData(struct bufmgr *,
unsigned buffer,
unsigned size, const void *data, unsigned flags);
void bmBufferSubData(struct bufmgr *,
unsigned buffer,
unsigned offset, unsigned size, const void *data);
void bmBufferGetSubData(struct bufmgr *,
unsigned buffer,
unsigned offset, unsigned size, void *data);
void *bmMapBuffer(struct bufmgr *, unsigned buffer, unsigned access);
void bmUnmapBuffer(struct bufmgr *, unsigned buffer);
/* To be called prior to emitting commands to hardware which reference
* these buffers.
*
* NewBufferList() and AddBuffer() build up a list of buffers to be
* validated. The buffer list provides information on where the
* buffers should be placed and whether their contents need to be
* preserved on copying. The offset data elements are return values
* from this function telling the driver exactly where the buffers are
* currently located.
*
* ValidateBufferList() performs the actual validation and returns the
* buffer pools and offsets within the pools.
*
* FenceBufferList() must be called to set fences and other
* housekeeping before unlocking after a successful call to
* ValidateBufferList(). The buffer manager knows how to emit and test
* fences directly through the drm and without callbacks to the
* driver.
*/
struct _drmMMBufList *bmNewBufferList(void);
int bmAddBuffer(struct bufmgr *bm,
struct _drmMMBufList *list,
unsigned buffer,
unsigned flags,
unsigned *pool_return, unsigned long *offset_return);
int bmValidateBufferList(struct bufmgr *,
struct _drmMMBufList *, unsigned flags);
unsigned bmFenceBufferList(struct bufmgr *, struct _drmMMBufList *);
void bmFreeBufferList(struct _drmMMBufList *);
int bmScanBufferList(struct bufmgr *bm,
struct _drmMMBufList *list, unsigned buffer);
/* This functionality is used by the buffer manager, not really sure
* if we need to be exposing it in this way, probably libdrm will
* offer equivalent calls.
*
* For now they can stay, but will likely change/move before final:
*/
unsigned bmSetFence(struct bufmgr *);
int bmTestFence(struct bufmgr *, unsigned fence);
void bmFinishFence(struct bufmgr *, unsigned fence);
unsigned bmInitFence(struct bufmgr *bm);
void bmSetShared(struct bufmgr *bm, unsigned buffer,
unsigned flags, unsigned long offset, void *virtual);
extern int INTEL_DEBUG;
#define DEBUG_BUFMGR 0x2000
#define DBG(...) do { if (INTEL_DEBUG & DEBUG_BUFMGR) _mesa_printf(__VA_ARGS__); } while(0)
#endif

View file

@ -0,0 +1,281 @@
/**************************************************************************
*
* Copyright 2006 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 "glheader.h"
#include "imports.h"
#include "context.h"
#include "depthstencil.h"
#include "fbobject.h"
#include "framebuffer.h"
#include "hash.h"
#include "mtypes.h"
#include "renderbuffer.h"
#include "intel_context.h"
#include "intel_fbo.h"
#include "intel_depthstencil.h"
#include "intel_regions.h"
/**
* The GL_EXT_framebuffer_object allows the user to create their own
* framebuffer objects consisting of color renderbuffers (0 or more),
* depth renderbuffers (0 or 1) and stencil renderbuffers (0 or 1).
*
* The spec considers depth and stencil renderbuffers to be totally independent
* buffers. In reality, most graphics hardware today uses a combined
* depth+stencil buffer (one 32-bit pixel = 24 bits of Z + 8 bits of stencil).
*
* This causes difficulty because the user may create some number of depth
* renderbuffers and some number of stencil renderbuffers and bind them
* together in framebuffers in any combination.
*
* This code manages all that.
*
* 1. Depth renderbuffers are always allocated in hardware as 32bpp
* GL_DEPTH24_STENCIL8 buffers.
*
* 2. Stencil renderbuffers are initially allocated in software as 8bpp
* GL_STENCIL_INDEX8 buffers.
*
* 3. Depth and Stencil renderbuffers use the PairedStencil and PairedDepth
* fields (respectively) to indicate if the buffer's currently paired
* with another stencil or depth buffer (respectively).
*
* 4. When a depth and stencil buffer are initially both attached to the
* current framebuffer, we merge the stencil buffer values into the
* depth buffer (really a depth+stencil buffer). The then hardware uses
* the combined buffer.
*
* 5. Whenever a depth or stencil buffer is reallocated (with
* glRenderbufferStorage) we undo the pairing and copy the stencil values
* from the combined depth/stencil buffer back to the stencil-only buffer.
*
* 6. We also undo the pairing when we find a change in buffer bindings.
*
* 7. If a framebuffer is only using a depth renderbuffer (no stencil), we
* just use the combined depth/stencil buffer and ignore the stencil values.
*
* 8. If a framebuffer is only using a stencil renderbuffer (no depth) we have
* to promote the 8bpp software stencil buffer to a 32bpp hardware
* depth+stencil buffer.
*
*/
static void
map_regions(GLcontext *ctx,
struct intel_renderbuffer *depthRb,
struct intel_renderbuffer *stencilRb)
{
struct intel_context *intel = intel_context(ctx);
if (depthRb && depthRb->region) {
intel_region_map(intel, depthRb->region);
depthRb->pfMap = depthRb->region->map;
depthRb->pfPitch = depthRb->region->pitch;
}
if (stencilRb && stencilRb->region) {
intel_region_map(intel, stencilRb->region);
stencilRb->pfMap = stencilRb->region->map;
stencilRb->pfPitch = stencilRb->region->pitch;
}
}
static void
unmap_regions(GLcontext *ctx,
struct intel_renderbuffer *depthRb,
struct intel_renderbuffer *stencilRb)
{
struct intel_context *intel = intel_context(ctx);
if (depthRb && depthRb->region) {
intel_region_unmap(intel, depthRb->region);
depthRb->pfMap = NULL;
depthRb->pfPitch = 0;
}
if (stencilRb && stencilRb->region) {
intel_region_unmap(intel, stencilRb->region);
stencilRb->pfMap = NULL;
stencilRb->pfPitch = 0;
}
}
/**
* Undo the pairing/interleaving between depth and stencil buffers.
* irb should be a depth/stencil or stencil renderbuffer.
*/
void
intel_unpair_depth_stencil(GLcontext *ctx, struct intel_renderbuffer *irb)
{
if (irb->PairedStencil) {
/* irb is a depth/stencil buffer */
struct gl_renderbuffer *stencilRb;
struct intel_renderbuffer *stencilIrb;
ASSERT(irb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
stencilRb = _mesa_lookup_renderbuffer(ctx, irb->PairedStencil);
stencilIrb = intel_renderbuffer(stencilRb);
if (stencilIrb) {
/* need to extract stencil values from the depth buffer */
ASSERT(stencilIrb->PairedDepth == irb->Base.Name);
map_regions(ctx, irb, stencilIrb);
_mesa_extract_stencil(ctx, &irb->Base, &stencilIrb->Base);
unmap_regions(ctx, irb, stencilIrb);
stencilIrb->PairedDepth = 0;
}
irb->PairedStencil = 0;
}
else if (irb->PairedDepth) {
/* irb is a stencil buffer */
struct gl_renderbuffer *depthRb;
struct intel_renderbuffer *depthIrb;
ASSERT(irb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT ||
irb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
depthRb = _mesa_lookup_renderbuffer(ctx, irb->PairedDepth);
depthIrb = intel_renderbuffer(depthRb);
if (depthIrb) {
/* need to extract stencil values from the depth buffer */
ASSERT(depthIrb->PairedStencil == irb->Base.Name);
map_regions(ctx, depthIrb, irb);
_mesa_extract_stencil(ctx, &depthIrb->Base, &irb->Base);
unmap_regions(ctx, depthIrb, irb);
depthIrb->PairedStencil = 0;
}
irb->PairedDepth = 0;
}
else {
_mesa_problem(ctx, "Problem in undo_depth_stencil_pairing");
}
ASSERT(irb->PairedStencil == 0);
ASSERT(irb->PairedDepth == 0);
}
/**
* Examine the depth and stencil renderbuffers which are attached to the
* framebuffer. If both depth and stencil are attached, make sure that the
* renderbuffers are 'paired' (combined). If only depth or only stencil is
* attached, undo any previous pairing.
*
* Must be called if NewState & _NEW_BUFFER (when renderbuffer attachments
* change, for example).
*/
void
intel_validate_paired_depth_stencil(GLcontext *ctx, struct gl_framebuffer *fb)
{
struct intel_renderbuffer *depthRb, *stencilRb;
depthRb = intel_get_renderbuffer(fb, BUFFER_DEPTH);
stencilRb = intel_get_renderbuffer(fb, BUFFER_STENCIL);
if (depthRb && stencilRb) {
if (depthRb == stencilRb) {
/* Using a user-created combined depth/stencil buffer.
* Nothing to do.
*/
ASSERT(depthRb->Base._BaseFormat == GL_DEPTH_STENCIL_EXT);
ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
}
else {
/* Separate depth/stencil buffers, need to interleave now */
ASSERT(depthRb->Base._BaseFormat == GL_DEPTH_COMPONENT);
ASSERT(stencilRb->Base._BaseFormat == GL_STENCIL_INDEX);
/* may need to interleave depth/stencil now */
if (depthRb->PairedStencil == stencilRb->Base.Name) {
/* OK, the depth and stencil buffers are already interleaved */
ASSERT(stencilRb->PairedDepth == depthRb->Base.Name);
}
else {
/* need to setup new pairing/interleaving */
if (depthRb->PairedStencil) {
intel_unpair_depth_stencil(ctx, depthRb);
}
if (stencilRb->PairedDepth) {
intel_unpair_depth_stencil(ctx, stencilRb);
}
ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
ASSERT(stencilRb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT ||
stencilRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
/* establish new pairing: interleave stencil into depth buffer */
map_regions(ctx, depthRb, stencilRb);
_mesa_insert_stencil(ctx, &depthRb->Base, &stencilRb->Base);
unmap_regions(ctx, depthRb, stencilRb);
depthRb->PairedStencil = stencilRb->Base.Name;
stencilRb->PairedDepth = depthRb->Base.Name;
}
}
}
else if (depthRb) {
/* Depth buffer but no stencil buffer.
* We'll use a GL_DEPTH24_STENCIL8 buffer and ignore the stencil bits.
*/
/* can't assert this until storage is allocated:
ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
*/
/* intel_undo any previous pairing */
if (depthRb->PairedStencil) {
intel_unpair_depth_stencil(ctx, depthRb);
}
}
else if (stencilRb) {
/* Stencil buffer but no depth buffer.
* Since h/w doesn't typically support just 8bpp stencil w/out Z,
* we'll use a GL_DEPTH24_STENCIL8 buffer and ignore the depth bits.
*/
/* undo any previous pairing */
if (stencilRb->PairedDepth) {
intel_unpair_depth_stencil(ctx, stencilRb);
}
if (stencilRb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT) {
/* promote buffer to GL_DEPTH24_STENCIL8 for hw rendering */
_mesa_promote_stencil(ctx, &stencilRb->Base);
ASSERT(stencilRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
}
}
/* Finally, update the fb->_DepthBuffer and fb->_StencilBuffer fields */
_mesa_update_depth_buffer(ctx, fb, BUFFER_DEPTH);
if (depthRb && depthRb->PairedStencil)
_mesa_update_stencil_buffer(ctx, fb, BUFFER_DEPTH);
else
_mesa_update_stencil_buffer(ctx, fb, BUFFER_STENCIL);
/* The hardware should use fb->Attachment[BUFFER_DEPTH].Renderbuffer
* first, if present, then fb->Attachment[BUFFER_STENCIL].Renderbuffer
* if present.
*/
}

View file

@ -0,0 +1,13 @@
#ifndef INTEL_DEPTH_STENCIL_H
#define INTEL_DEPTH_STENCIL_H
extern void
intel_unpair_depth_stencil(GLcontext *ctx, struct intel_renderbuffer *irb);
extern void
intel_validate_paired_depth_stencil(GLcontext *ctx, struct gl_framebuffer *fb);
#endif /* INTEL_DEPTH_STENCIL_H */

View file

@ -0,0 +1,639 @@
/**************************************************************************
*
* Copyright 2006 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 "imports.h"
#include "mtypes.h"
#include "fbobject.h"
#include "framebuffer.h"
#include "renderbuffer.h"
#include "context.h"
#include "texformat.h"
#include "texrender.h"
#include "intel_context.h"
#include "intel_buffers.h"
#include "intel_bufmgr.h"
#include "intel_depthstencil.h"
#include "intel_fbo.h"
#include "intel_mipmap_tree.h"
#include "intel_regions.h"
#include "intel_span.h"
#define INTEL_RB_CLASS 0x12345678
/* XXX FBO: move this to intel_context.h (inlined) */
/**
* Return a gl_renderbuffer ptr casted to intel_renderbuffer.
* NULL will be returned if the rb isn't really an intel_renderbuffer.
* This is determiend by checking the ClassID.
*/
struct intel_renderbuffer *intel_renderbuffer( struct gl_renderbuffer *rb )
{
struct intel_renderbuffer *irb = (struct intel_renderbuffer *) rb;
if (irb && irb->Base.ClassID == INTEL_RB_CLASS) {
/*_mesa_warning(NULL, "Returning non-intel Rb\n");*/
return irb;
}
else
return NULL;
}
struct intel_renderbuffer *
intel_get_renderbuffer(struct gl_framebuffer *fb, GLuint attIndex)
{
return intel_renderbuffer(fb->Attachment[attIndex].Renderbuffer);
}
struct intel_region *
intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex)
{
struct intel_renderbuffer *irb
= intel_renderbuffer(fb->Attachment[attIndex].Renderbuffer);
if (irb)
return irb->region;
else
return NULL;
}
/**
* Create a new framebuffer object.
*/
static struct gl_framebuffer *
intel_new_framebuffer(GLcontext *ctx, GLuint name)
{
/* there's no intel_framebuffer at this time, just use Mesa's class */
return _mesa_new_framebuffer(ctx, name);
}
static void
intel_delete_renderbuffer(struct gl_renderbuffer *rb)
{
GET_CURRENT_CONTEXT(ctx);
struct intel_context *intel = intel_context(ctx);
struct intel_renderbuffer *irb = intel_renderbuffer(rb);
ASSERT(irb);
if (irb->PairedStencil || irb->PairedDepth) {
intel_unpair_depth_stencil(ctx, irb);
}
if (intel && irb->region) {
intel_region_release(intel, &irb->region);
}
_mesa_free(irb);
}
/**
* Return a pointer to a specific pixel in a renderbuffer.
*/
static void *
intel_get_pointer(GLcontext *ctx, struct gl_renderbuffer *rb,
GLint x, GLint y)
{
/* By returning NULL we force all software rendering to go through
* the span routines.
*/
return NULL;
}
/**
* Called via glRenderbufferStorageEXT() to set the format and allocate
* storage for a user-created renderbuffer.
*/
static GLboolean
intel_alloc_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
GLenum internalFormat,
GLuint width, GLuint height)
{
struct intel_context *intel = intel_context(ctx);
struct intel_renderbuffer *irb = intel_renderbuffer(rb);
GLboolean softwareBuffer = GL_FALSE;
int cpp;
ASSERT(rb->Name != 0);
switch (internalFormat) {
case GL_R3_G3_B2:
case GL_RGB4:
case GL_RGB5:
rb->_ActualFormat = GL_RGB5;
rb->DataType = GL_UNSIGNED_BYTE;
rb->RedBits = 5;
rb->GreenBits = 6;
rb->BlueBits = 5;
cpp = 2;
break;
case GL_RGB:
case GL_RGB8:
case GL_RGB10:
case GL_RGB12:
case GL_RGB16:
case GL_RGBA:
case GL_RGBA2:
case GL_RGBA4:
case GL_RGB5_A1:
case GL_RGBA8:
case GL_RGB10_A2:
case GL_RGBA12:
case GL_RGBA16:
rb->_ActualFormat = GL_RGBA8;
rb->DataType = GL_UNSIGNED_BYTE;
rb->RedBits = 8;
rb->GreenBits = 8;
rb->BlueBits = 8;
rb->AlphaBits = 8;
cpp = 4;
break;
case GL_STENCIL_INDEX:
case GL_STENCIL_INDEX1_EXT:
case GL_STENCIL_INDEX4_EXT:
case GL_STENCIL_INDEX8_EXT:
case GL_STENCIL_INDEX16_EXT:
/* alloc a depth+stencil buffer */
rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
rb->StencilBits = 8;
cpp = 4;
break;
case GL_DEPTH_COMPONENT16:
rb->_ActualFormat = GL_DEPTH_COMPONENT16;
rb->DataType = GL_UNSIGNED_SHORT;
rb->DepthBits = 16;
cpp = 2;
break;
case GL_DEPTH_COMPONENT:
case GL_DEPTH_COMPONENT24:
case GL_DEPTH_COMPONENT32:
rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
rb->DepthBits = 24;
cpp = 4;
break;
case GL_DEPTH_STENCIL_EXT:
case GL_DEPTH24_STENCIL8_EXT:
rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
rb->DepthBits = 24;
rb->StencilBits = 8;
cpp = 4;
break;
default:
_mesa_problem(ctx, "Unexpected format in intel_alloc_renderbuffer_storage");
return GL_FALSE;
}
intelFlush(ctx);
/* free old region */
if (irb->region) {
/*LOCK_HARDWARE(intel);*/
intel_region_release(intel, &irb->region);
/*UNLOCK_HARDWARE(intel);*/
}
/* allocate new memory region/renderbuffer */
if (softwareBuffer) {
return _mesa_soft_renderbuffer_storage(ctx, rb, internalFormat,
width, height);
}
else {
/* Choose a pitch to match hardware requirements:
*/
GLuint pitch = ((cpp * width + 63) & ~63) / cpp;
/* alloc hardware renderbuffer */
_mesa_debug(ctx, "Allocating %d x %d Intel RBO (pitch %d)\n", width, height, pitch);
irb->region = intel_region_alloc(intel, cpp, pitch, height);
if (!irb->region)
return GL_FALSE; /* out of memory? */
ASSERT(irb->region->buffer);
rb->Width = width;
rb->Height = height;
/* This sets the Get/PutRow/Value functions */
intel_set_span_functions(&irb->Base);
return GL_TRUE;
}
}
/**
* Called for each hardware renderbuffer when a _window_ is resized.
* Just update fields.
* Not used for user-created renderbuffers!
*/
static GLboolean
intel_alloc_window_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
GLenum internalFormat,
GLuint width, GLuint height)
{
ASSERT(rb->Name == 0);
rb->Width = width;
rb->Height = height;
rb->_ActualFormat = internalFormat;
return GL_TRUE;
}
static GLboolean
intel_nop_alloc_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
GLenum internalFormat,
GLuint width, GLuint height)
{
_mesa_problem(ctx, "intel_op_alloc_storage should never be called.");
return GL_FALSE;
}
/**
* Create a new intel_renderbuffer which corresponds to an on-screen window,
* not a user-created renderbuffer.
* \param width the screen width
* \param height the screen height
*/
struct intel_renderbuffer *
intel_create_renderbuffer(GLenum intFormat, GLsizei width, GLsizei height,
int offset, int pitch, int cpp, void *map)
{
GET_CURRENT_CONTEXT(ctx);
struct intel_renderbuffer *irb;
const GLuint name = 0;
irb = CALLOC_STRUCT(intel_renderbuffer);
if (!irb) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
return NULL;
}
_mesa_init_renderbuffer(&irb->Base, name);
irb->Base.ClassID = INTEL_RB_CLASS;
switch (intFormat) {
case GL_RGB5:
irb->Base._ActualFormat = GL_RGB5;
irb->Base._BaseFormat = GL_RGBA;
irb->Base.RedBits = 5;
irb->Base.GreenBits = 6;
irb->Base.BlueBits = 5;
irb->Base.DataType = GL_UNSIGNED_BYTE;
cpp = 2;
break;
case GL_RGBA8:
irb->Base._ActualFormat = GL_RGBA8;
irb->Base._BaseFormat = GL_RGBA;
irb->Base.RedBits = 8;
irb->Base.GreenBits = 8;
irb->Base.BlueBits = 8;
irb->Base.AlphaBits = 8;
irb->Base.DataType = GL_UNSIGNED_BYTE;
cpp = 4;
break;
case GL_STENCIL_INDEX8_EXT:
irb->Base._ActualFormat = GL_STENCIL_INDEX8_EXT;
irb->Base._BaseFormat = GL_STENCIL_INDEX;
irb->Base.StencilBits = 8;
irb->Base.DataType = GL_UNSIGNED_BYTE;
cpp = 1;
break;
case GL_DEPTH_COMPONENT16:
irb->Base._ActualFormat = GL_DEPTH_COMPONENT16;
irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
irb->Base.DepthBits = 16;
irb->Base.DataType = GL_UNSIGNED_SHORT;
cpp = 2;
break;
case GL_DEPTH_COMPONENT24:
irb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
irb->Base.DepthBits = 24;
irb->Base.DataType = GL_UNSIGNED_INT;
cpp = 4;
break;
case GL_DEPTH24_STENCIL8_EXT:
irb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
irb->Base._BaseFormat = GL_DEPTH_STENCIL_EXT;
irb->Base.DepthBits = 24;
irb->Base.StencilBits = 8;
irb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
cpp = 4;
break;
default:
_mesa_problem(NULL, "Unexpected intFormat in intel_create_renderbuffer");
return NULL;
}
irb->Base.InternalFormat = intFormat;
/* intel-specific methods */
irb->Base.Delete = intel_delete_renderbuffer;
irb->Base.AllocStorage = intel_alloc_window_storage;
irb->Base.GetPointer = intel_get_pointer;
/* This sets the Get/PutRow/Value functions */
intel_set_span_functions(&irb->Base);
irb->pfMap = map;
irb->pfPitch = pitch;
#if 00
irb->region = intel_region_create_static(intel,
DRM_MM_TT,
offset,
map,
cpp,
width, height);
#endif
return irb;
}
/**
* Create a new renderbuffer object.
* Typically called via glBindRenderbufferEXT().
*/
static struct gl_renderbuffer *
intel_new_renderbuffer(GLcontext *ctx, GLuint name)
{
/*struct intel_context *intel = intel_context(ctx);*/
struct intel_renderbuffer *irb;
irb = CALLOC_STRUCT(intel_renderbuffer);
if (!irb) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
return NULL;
}
_mesa_init_renderbuffer(&irb->Base, name);
irb->Base.ClassID = INTEL_RB_CLASS;
/* intel-specific methods */
irb->Base.Delete = intel_delete_renderbuffer;
irb->Base.AllocStorage = intel_alloc_renderbuffer_storage;
irb->Base.GetPointer = intel_get_pointer;
/* span routines set in alloc_storage function */
return &irb->Base;
}
/**
* Called via glBindFramebufferEXT().
*/
static void
intel_bind_framebuffer(GLcontext *ctx, GLenum target,
struct gl_framebuffer *fb)
{
/*
_mesa_debug(ctx, "%s %d\n", __FUNCTION__, fb->Name);
*/
/* XXX FBO: putting this flush here fixes a rendering offset bug.
* Not sure why this is needed when _mesa_BindFrameBuffer does
* a FLUSH_VERTICES().
*/
intelFlush(ctx);
if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
intel_draw_buffer(ctx, fb);
/* Integer depth range depends on depth buffer bits */
ctx->Driver.DepthRange(ctx, ctx->Viewport.Near, ctx->Viewport.Far);
}
else {
/* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
}
}
/**
* Called via glFramebufferRenderbufferEXT().
*/
static void
intel_framebuffer_renderbuffer(GLcontext *ctx,
struct gl_framebuffer *fb,
GLenum attachment,
struct gl_renderbuffer *rb)
{
/*
_mesa_debug(ctx, "Intel FramebufferRenderbuffer %u %u\n",
fb->Name, rb ? rb->Name : 0);
*/
intelFlush(ctx);
_mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
intel_draw_buffer(ctx, fb);
}
/**
* When glFramebufferTexture[123]D is called this function sets up the
* gl_renderbuffer wrapp around the texture image.
* This will have the region info needed for hardware rendering.
*/
static struct intel_renderbuffer *
intel_wrap_texture(GLcontext *ctx, struct gl_texture_image *texImage)
{
const GLuint name = ~0; /* not significant, but distinct for debugging */
struct intel_renderbuffer *irb;
/* make an intel_renderbuffer to wrap the texture image */
irb = CALLOC_STRUCT(intel_renderbuffer);
if (!irb) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture");
return NULL;
}
_mesa_init_renderbuffer(&irb->Base, name);
irb->Base.ClassID = INTEL_RB_CLASS;
if (texImage->TexFormat == &_mesa_texformat_argb8888) {
irb->Base._ActualFormat = GL_RGBA8;
irb->Base._BaseFormat = GL_RGBA;
_mesa_debug(ctx, "Render to RGBA8 texture OK\n");
}
else if (texImage->TexFormat == &_mesa_texformat_rgb565) {
irb->Base._ActualFormat = GL_RGB5;
irb->Base._BaseFormat = GL_RGB;
_mesa_debug(ctx, "Render to RGB5 texture OK\n");
}
else if (texImage->TexFormat == &_mesa_texformat_z16) {
irb->Base._ActualFormat = GL_DEPTH_COMPONENT16;
irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
_mesa_debug(ctx, "Render to DEPTH16 texture OK\n");
}
else {
_mesa_debug(ctx, "Render to texture BAD FORMAT %d\n", texImage->TexFormat->MesaFormat);
_mesa_free(irb);
return NULL;
}
irb->Base.InternalFormat = irb->Base._ActualFormat;
irb->Base.Width = texImage->Width;
irb->Base.Height = texImage->Height;
irb->Base.DataType = GL_UNSIGNED_BYTE; /* FBO XXX fix */
irb->Base.RedBits = texImage->TexFormat->RedBits;
irb->Base.GreenBits = texImage->TexFormat->GreenBits;
irb->Base.BlueBits = texImage->TexFormat->BlueBits;
irb->Base.AlphaBits = texImage->TexFormat->AlphaBits;
irb->Base.DepthBits = texImage->TexFormat->DepthBits;
irb->Base.Delete = intel_delete_renderbuffer;
irb->Base.AllocStorage = intel_nop_alloc_storage;
intel_set_span_functions(&irb->Base);
irb->RenderToTexture = GL_TRUE;
return irb;
}
/**
* Called by glFramebufferTexture[123]DEXT() (and other places) to
* prepare for rendering into texture memory. This might be called
* many times to choose different texture levels, cube faces, etc
* before intel_finish_render_texture() is ever called.
*/
static void
intel_render_texture(GLcontext *ctx,
struct gl_framebuffer *fb,
struct gl_renderbuffer_attachment *att)
{
struct gl_texture_image *newImage
= att->Texture->Image[att->CubeMapFace][att->TextureLevel];
struct intel_renderbuffer *irb
= intel_renderbuffer(att->Renderbuffer);
struct intel_texture_image *intel_image;
GLuint imageOffset;
(void) fb;
ASSERT(newImage);
if (!irb) {
irb = intel_wrap_texture(ctx, newImage);
if (irb) {
/* bind the wrapper to the attachment point */
att->Renderbuffer = &irb->Base;
}
else {
/* fallback to software rendering */
_mesa_render_texture(ctx, fb, att);
return;
}
}
/*
_mesa_debug(ctx, "Begin render texture tex=%u w=%d h=%d refcount=%d\n",
att->Texture->Name, newImage->Width, newImage->Height,
irb->Base.RefCount);
*/
/* point the renderbufer's region to the texture image region */
intel_image = intel_texture_image(newImage);
if (irb->region != intel_image->mt->region)
intel_region_reference(&irb->region, intel_image->mt->region);
/* compute offset of the particular 2D image within the texture region */
imageOffset = intel_miptree_image_offset(intel_image->mt,
att->CubeMapFace,
att->TextureLevel);
if (att->Texture->Target == GL_TEXTURE_3D) {
const GLuint *offsets = intel_miptree_depth_offsets(intel_image->mt,
att->TextureLevel);
imageOffset += offsets[att->Zoffset];
}
/* store that offset in the region */
intel_image->mt->region->draw_offset = imageOffset;
/* update drawing region, etc */
intel_draw_buffer(ctx, fb);
}
/**
* Called by Mesa when rendering to a texture is done.
*/
static void
intel_finish_render_texture(GLcontext *ctx,
struct gl_renderbuffer_attachment *att)
{
struct intel_context *intel = intel_context(ctx);
struct intel_renderbuffer *irb
= intel_renderbuffer(att->Renderbuffer);
/*
_mesa_debug(ctx, "End render texture (tid %u) tex %u\n",
_glthread_GetID(), att->Texture->Name);
*/
if (irb) {
/* just release the region */
intel_region_release(intel, &irb->region);
}
else if (att->Renderbuffer) {
/* software fallback */
_mesa_finish_render_texture(ctx, att);
/* XXX FBO: Need to unmap the buffer (or in intelSpanRenderStart???) */
}
}
/**
* Do one-time context initializations related to GL_EXT_framebuffer_object.
* Hook in device driver functions.
*/
void
intel_fbo_init( struct intel_context *intel )
{
intel->ctx.Driver.NewFramebuffer = intel_new_framebuffer;
intel->ctx.Driver.NewRenderbuffer = intel_new_renderbuffer;
intel->ctx.Driver.BindFramebuffer = intel_bind_framebuffer;
intel->ctx.Driver.FramebufferRenderbuffer = intel_framebuffer_renderbuffer;
intel->ctx.Driver.RenderTexture = intel_render_texture;
intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture;
}

View file

@ -0,0 +1,75 @@
/**************************************************************************
*
* Copyright 2006 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.
*
**************************************************************************/
#ifndef INTEL_FBO_H
#define INTEL_FBO_H
struct intel_context;
struct intel_region;
/**
* Intel renderbuffer, derived from gl_renderbuffer.
* Note: The PairedDepth and PairedStencil fields use renderbuffer IDs,
* not pointers because in some circumstances a deleted renderbuffer could
* result in a dangling pointer here.
*/
struct intel_renderbuffer {
struct gl_renderbuffer Base;
struct intel_region *region;
void *pfMap; /* possibly paged flipped map pointer */
GLuint pfPitch; /* possibly paged flipped pitch */
GLboolean RenderToTexture; /* RTT? */
GLuint PairedDepth; /**< only used if this is a depth renderbuffer */
GLuint PairedStencil; /**< only used if this is a stencil renderbuffer */
};
extern struct intel_renderbuffer *
intel_create_renderbuffer(GLenum intFormat, GLsizei width, GLsizei height,
int offset, int pitch, int cpp, void *map);
extern void
intel_fbo_init( struct intel_context *intel );
/* XXX make inline or macro */
extern struct intel_renderbuffer *
intel_get_renderbuffer(struct gl_framebuffer *fb, GLuint attIndex);
/* XXX make inline or macro */
extern struct intel_region *
intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex);
#endif /* INTEL_FBO_H */

View file

@ -0,0 +1,359 @@
/**************************************************************************
*
* Copyright 2006 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_context.h"
#include "intel_mipmap_tree.h"
#include "intel_regions.h"
#include "intel_bufmgr.h"
#include "enums.h"
static GLenum target_to_target( GLenum target )
{
switch (target) {
case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
return GL_TEXTURE_CUBE_MAP_ARB;
default:
return target;
}
}
struct intel_mipmap_tree *intel_miptree_create( struct intel_context *intel,
GLenum target,
GLenum internal_format,
GLuint first_level,
GLuint last_level,
GLuint width0,
GLuint height0,
GLuint depth0,
GLuint cpp,
GLboolean compressed)
{
GLboolean ok;
struct intel_mipmap_tree *mt = calloc(sizeof(*mt), 1);
DBG("%s target %s format %s level %d..%d\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(target),
_mesa_lookup_enum_by_nr(internal_format),
first_level,
last_level);
mt->target = target_to_target(target);
mt->internal_format = internal_format;
mt->first_level = first_level;
mt->last_level = last_level;
mt->width0 = width0;
mt->height0 = height0;
mt->depth0 = depth0;
mt->cpp = cpp;
mt->compressed = compressed;
mt->refcount = 1;
switch (intel->intelScreen->deviceID) {
case PCI_CHIP_I945_G:
case PCI_CHIP_I945_GM:
ok = i945_miptree_layout( mt );
break;
case PCI_CHIP_I915_G:
case PCI_CHIP_I915_GM:
case PCI_CHIP_I830_M:
case PCI_CHIP_I855_GM:
case PCI_CHIP_I865_G:
default:
/* All the i830 chips and the i915 use this layout:
*/
ok = i915_miptree_layout( mt );
break;
}
if (ok)
mt->region = intel_region_alloc( intel,
mt->cpp,
mt->pitch,
mt->total_height );
if (!mt->region) {
free(mt);
return NULL;
}
return mt;
}
void intel_miptree_reference( struct intel_mipmap_tree **dst,
struct intel_mipmap_tree *src )
{
src->refcount++;
*dst = src;
}
void intel_miptree_release( struct intel_context *intel,
struct intel_mipmap_tree **mt )
{
if (!*mt)
return;
DBG("%s %d\n", __FUNCTION__, (*mt)->refcount-1);
if (--(*mt)->refcount == 0) {
GLuint i;
intel_region_release(intel, &((*mt)->region));
for (i = 0; i < MAX_TEXTURE_LEVELS; i++)
if ((*mt)->level[i].image_offset)
free((*mt)->level[i].image_offset);
free(*mt);
}
*mt = NULL;
}
/* Can the image be pulled into a unified mipmap tree. This mirrors
* the completeness test in a lot of ways.
*
* Not sure whether I want to pass gl_texture_image here.
*/
GLboolean intel_miptree_match_image( struct intel_mipmap_tree *mt,
struct gl_texture_image *image,
GLuint face,
GLuint level )
{
DBG("%s %d %d/%d %d/%d\n", __FUNCTION__,
image->Border,
image->InternalFormat, mt->internal_format,
image->IsCompressed, mt->compressed);
/* Images with borders are never pulled into mipmap trees.
*/
if (image->Border)
return GL_FALSE;
if (image->InternalFormat != mt->internal_format ||
image->IsCompressed != mt->compressed)
return GL_FALSE;
_mesa_printf("%s: %d/%d %d/%d %d/%d\n", __FUNCTION__,
image->Width, mt->level[level].width,
image->Height, mt->level[level].height,
image->Depth, mt->level[level].depth);
/* Test image dimensions against the base level image adjusted for
* minification. This will also catch images not present in the
* tree, changed targets, etc.
*/
if (image->Width != mt->level[level].width ||
image->Height != mt->level[level].height ||
image->Depth != mt->level[level].depth)
return GL_FALSE;
DBG("%s: success\n", __FUNCTION__);
return GL_TRUE;
}
void intel_miptree_set_level_info(struct intel_mipmap_tree *mt,
GLuint level,
GLuint nr_images,
GLuint x, GLuint y,
GLuint w, GLuint h, GLuint d)
{
mt->level[level].width = w;
mt->level[level].height = h;
mt->level[level].depth = d;
mt->level[level].level_offset = (x + y * mt->pitch) * mt->cpp;
mt->level[level].nr_images = nr_images;
_mesa_printf("%s level %d img size: %d,%d level_offset 0x%x\n", __FUNCTION__, level, w, h,
mt->level[level].level_offset);
/* Not sure when this would happen, but anyway:
*/
if (mt->level[level].image_offset) {
free(mt->level[level].image_offset);
mt->level[level].image_offset = NULL;
}
assert(nr_images);
mt->level[level].image_offset = malloc(nr_images * sizeof(GLuint));
mt->level[level].image_offset[0] = 0;
}
void intel_miptree_set_image_offset(struct intel_mipmap_tree *mt,
GLuint level,
GLuint img,
GLuint x, GLuint y)
{
_mesa_printf("%s level %d img %d pos %d,%d\n", __FUNCTION__, level, img, x, y);
if (img == 0)
assert(x == 0 && y == 0);
if (img > 0)
mt->level[level].image_offset[img] = (x + y * mt->pitch) * mt->cpp;
}
/* Although we use the image_offset[] array to store relative offsets
* to cube faces, Mesa doesn't know anything about this and expects
* each cube face to be treated as a separate image.
*
* These functions present that view to mesa:
*/
const GLuint *intel_miptree_depth_offsets(struct intel_mipmap_tree *mt,
GLuint level)
{
static const GLuint zero = 0;
if (mt->target != GL_TEXTURE_3D ||
mt->level[level].nr_images == 1)
return &zero;
else
return mt->level[level].image_offset;
}
GLuint intel_miptree_image_offset(struct intel_mipmap_tree *mt,
GLuint face,
GLuint level)
{
if (mt->target == GL_TEXTURE_CUBE_MAP_ARB)
return (mt->level[level].level_offset +
mt->level[level].image_offset[face]);
else
return mt->level[level].level_offset;
}
/**
* Map a teximage in a mipmap tree.
* \param row_stride returns row stride in bytes
* \param image_stride returns image stride in bytes (for 3D textures).
* \return address of mapping
*/
GLubyte *intel_miptree_image_map(struct intel_context *intel,
struct intel_mipmap_tree *mt,
GLuint face,
GLuint level,
GLuint *row_stride,
GLuint *image_offsets)
{
DBG("%s \n", __FUNCTION__);
if (row_stride)
*row_stride = mt->pitch * mt->cpp;
if (image_offsets)
memcpy(image_offsets, mt->level[level].image_offset,
mt->level[level].depth * sizeof(GLuint));
return (intel_region_map(intel, mt->region) +
intel_miptree_image_offset(mt, face, level));
}
void intel_miptree_image_unmap(struct intel_context *intel,
struct intel_mipmap_tree *mt)
{
DBG("%s\n", __FUNCTION__);
intel_region_unmap(intel, mt->region);
}
/* Upload data for a particular image.
*/
void intel_miptree_image_data(struct intel_context *intel,
struct intel_mipmap_tree *dst,
GLuint face,
GLuint level,
void *src,
GLuint src_row_pitch,
GLuint src_image_pitch)
{
GLuint depth = dst->level[level].depth;
GLuint dst_offset = intel_miptree_image_offset(dst, face, level);
const GLuint *dst_depth_offset = intel_miptree_depth_offsets(dst, level);
GLuint i;
DBG("%s\n", __FUNCTION__);
for (i = 0; i < depth; i++) {
intel_region_data(intel,
dst->region, dst_offset + dst_depth_offset[i],
0,
0,
src,
src_row_pitch,
0, 0, /* source x,y */
dst->level[level].width,
dst->level[level].height);
src += src_image_pitch;
}
}
/* Copy mipmap image between trees
*/
void intel_miptree_image_copy( struct intel_context *intel,
struct intel_mipmap_tree *dst,
GLuint face, GLuint level,
struct intel_mipmap_tree *src )
{
GLuint width = src->level[level].width;
GLuint height = src->level[level].height;
GLuint depth = src->level[level].depth;
GLuint dst_offset = intel_miptree_image_offset(dst, face, level);
GLuint src_offset = intel_miptree_image_offset(src, face, level);
const GLuint *dst_depth_offset = intel_miptree_depth_offsets(dst, level);
const GLuint *src_depth_offset = intel_miptree_depth_offsets(src, level);
GLuint i;
for (i = 0; i < depth; i++) {
intel_region_copy(intel,
dst->region, dst_offset + dst_depth_offset[i],
0,
0,
src->region, src_offset + src_depth_offset[i],
0,
0,
width,
height);
}
}

View file

@ -0,0 +1,201 @@
/**************************************************************************
*
* Copyright 2006 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.
*
**************************************************************************/
#ifndef INTEL_MIPMAP_TREE_H
#define INTEL_MIPMAP_TREE_H
#include "intel_regions.h"
/* A layer on top of the intel_regions code which adds:
*
* - Code to size and layout a region to hold a set of mipmaps.
* - Query to determine if a new image fits in an existing tree.
* - More refcounting
* - maybe able to remove refcounting from intel_region?
* - ?
*
* The fixed mipmap layout of intel hardware where one offset
* specifies the position of all images in a mipmap hierachy
* complicates the implementation of GL texture image commands,
* compared to hardware where each image is specified with an
* independent offset.
*
* In an ideal world, each texture object would be associated with a
* single bufmgr buffer or 2d intel_region, and all the images within
* the texture object would slot into the tree as they arrive. The
* reality can be a little messier, as images can arrive from the user
* with sizes that don't fit in the existing tree, or in an order
* where the tree layout cannot be guessed immediately.
*
* This structure encodes an idealized mipmap tree. The GL image
* commands build these where possible, otherwise store the images in
* temporary system buffers.
*/
/**
* Describes the location of each texture image within a texture region.
*/
struct intel_mipmap_level {
GLuint level_offset;
GLuint width;
GLuint height;
GLuint depth;
GLuint nr_images;
/* Explicitly store the offset of each image for each cube face or
* depth value. Pretty much have to accept that hardware formats
* are going to be so diverse that there is no unified way to
* compute the offsets of depth/cube images within a mipmap level,
* so have to store them as a lookup table:
*/
GLuint *image_offset;
};
struct intel_mipmap_tree {
/* Effectively the key:
*/
GLenum target;
GLenum internal_format;
GLuint first_level;
GLuint last_level;
GLuint width0, height0, depth0; /**< Level zero image dimensions */
GLuint cpp;
GLboolean compressed;
/* Derived from the above:
*/
GLuint pitch;
GLuint depth_pitch; /* per-image on i945? */
GLuint total_height;
/* Includes image offset tables:
*/
struct intel_mipmap_level level[MAX_TEXTURE_LEVELS];
/* The data is held here:
*/
struct intel_region *region;
/* These are also refcounted:
*/
GLuint refcount;
};
struct intel_mipmap_tree *intel_miptree_create( struct intel_context *intel,
GLenum target,
GLenum internal_format,
GLuint first_level,
GLuint last_level,
GLuint width0,
GLuint height0,
GLuint depth0,
GLuint cpp,
GLboolean compressed);
void intel_miptree_reference( struct intel_mipmap_tree **dst,
struct intel_mipmap_tree *src );
void intel_miptree_release( struct intel_context *intel,
struct intel_mipmap_tree **mt );
/* Check if an image fits an existing mipmap tree layout
*/
GLboolean intel_miptree_match_image( struct intel_mipmap_tree *mt,
struct gl_texture_image *image,
GLuint face,
GLuint level );
/* Return a pointer to an image within a tree. Return image stride as
* well.
*/
GLubyte *intel_miptree_image_map( struct intel_context *intel,
struct intel_mipmap_tree *mt,
GLuint face,
GLuint level,
GLuint *row_stride,
GLuint *image_stride);
void intel_miptree_image_unmap( struct intel_context *intel,
struct intel_mipmap_tree *mt );
/* Return the linear offset of an image relative to the start of the
* tree:
*/
GLuint intel_miptree_image_offset( struct intel_mipmap_tree *mt,
GLuint face,
GLuint level );
/* Return pointers to each 2d slice within an image. Indexed by depth
* value.
*/
const GLuint *intel_miptree_depth_offsets(struct intel_mipmap_tree *mt,
GLuint level);
void intel_miptree_set_level_info(struct intel_mipmap_tree *mt,
GLuint level,
GLuint nr_images,
GLuint x, GLuint y,
GLuint w, GLuint h, GLuint d);
void intel_miptree_set_image_offset(struct intel_mipmap_tree *mt,
GLuint level,
GLuint img,
GLuint x, GLuint y);
/* Upload an image into a tree
*/
void intel_miptree_image_data(struct intel_context *intel,
struct intel_mipmap_tree *dst,
GLuint face,
GLuint level,
void *src,
GLuint src_row_pitch,
GLuint src_image_pitch);
/* Copy an image between two trees
*/
void intel_miptree_image_copy( struct intel_context *intel,
struct intel_mipmap_tree *dst,
GLuint face, GLuint level,
struct intel_mipmap_tree *src );
/* i915_mipmap_tree.c:
*/
GLboolean i915_miptree_layout( struct intel_mipmap_tree *mt );
GLboolean i945_miptree_layout( struct intel_mipmap_tree *mt );
#endif

View file

@ -0,0 +1,64 @@
/**************************************************************************
*
* Copyright 2006 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.
*
**************************************************************************/
#ifndef INTEL_PIXEL_H
#define INTEL_PIXEL_H
#include "mtypes.h"
void intelInitPixelFuncs( struct dd_function_table *functions );
GLboolean intel_check_blit_fragment_ops( GLcontext *ctx );
GLboolean intel_check_meta_tex_fragment_ops( GLcontext *ctx );
GLboolean intel_check_blit_format( struct intel_region *region,
GLenum format, GLenum type );
void intelReadPixels( GLcontext *ctx,
GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *pack,
GLvoid *pixels );
void intelDrawPixels( GLcontext *ctx,
GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format,
GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels );
void intelCopyPixels( GLcontext *ctx,
GLint srcx, GLint srcy,
GLsizei width, GLsizei height,
GLint destx, GLint desty,
GLenum type );
#endif

View file

@ -0,0 +1,350 @@
/**************************************************************************
*
* 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 "glheader.h"
#include "enums.h"
#include "image.h"
#include "mtypes.h"
#include "macros.h"
#include "swrast/swrast.h"
#include "intel_screen.h"
#include "intel_context.h"
#include "intel_ioctl.h"
#include "intel_batchbuffer.h"
#include "intel_buffers.h"
#include "intel_blit.h"
#include "intel_regions.h"
#include "intel_tris.h"
#include "intel_pixel.h"
#include "intel_bufmgr.h"
static struct intel_region *copypix_src_region( struct intel_context *intel,
GLenum type )
{
switch (type) {
case GL_COLOR:
return intel_readbuf_region( intel );
case GL_DEPTH:
/* Don't think this is really possible execpt at 16bpp, when we have no stencil.
*/
if (intel->depth_region &&
intel->depth_region->cpp == 2)
return intel->depth_region;
case GL_STENCIL:
/* Don't think this is really possible.
*/
break;
case GL_DEPTH_STENCIL_EXT:
/* Does it matter whether it is stencil/depth or depth/stencil?
*/
return intel->depth_region;
default:
break;
}
return NULL;
}
/* Doesn't work for overlapping regions. Could do a double copy or
* just fallback.
*/
static GLboolean do_texture_copypixels( GLcontext *ctx,
GLint srcx, GLint srcy,
GLsizei width, GLsizei height,
GLint dstx, GLint dsty,
GLenum type )
{
struct intel_context *intel = intel_context( ctx );
struct intel_region *dst = intel_drawbuf_region( intel );
struct intel_region *src = copypix_src_region(intel, type);
GLenum src_format;
GLenum src_type;
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
if (!src || !dst || type != GL_COLOR)
return GL_FALSE;
/* Can't handle overlapping regions. Don't have sufficient control
* over rasterization to pull it off in-place. Punt on these for
* now.
*
* XXX: do a copy to a temporary.
*/
if (src->buffer == dst->buffer)
{
drm_clip_rect_t srcbox;
drm_clip_rect_t dstbox;
drm_clip_rect_t tmp;
srcbox.x1 = srcx;
srcbox.y1 = srcy;
srcbox.x2 = srcx + width;
srcbox.y2 = srcy + height;
dstbox.x1 = dstx;
dstbox.y1 = dsty;
dstbox.x1 = dstx + width * ctx->Pixel.ZoomX;
dstbox.y2 = dsty + height * ctx->Pixel.ZoomY;
if (intel_intersect_cliprects(&tmp, &srcbox, &dstbox)) {
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s: regions overlap\n", __FUNCTION__);
return GL_FALSE;
}
}
intelFlush( &intel->ctx );
intel->vtbl.install_meta_state(intel);
/* Is this true? Also will need to turn depth testing on according
* to state:
*/
intel->vtbl.meta_no_stencil_write(intel);
intel->vtbl.meta_no_depth_write(intel);
/* Set the 3d engine to draw into the destination region:
*/
intel->vtbl.meta_draw_region(intel, dst, intel->depth_region);
intel->vtbl.meta_import_pixel_state(intel);
if (src->cpp == 2) {
src_format = GL_RGB;
src_type = GL_UNSIGNED_SHORT_5_6_5;
}
else {
src_format = GL_BGRA;
src_type = GL_UNSIGNED_BYTE;
}
/* Set the frontbuffer up as a large rectangular texture.
*/
if (!intel->vtbl.meta_tex_rect_source( intel, src->buffer, 0,
src->pitch,
src->height,
src_format,
src_type )) {
intel->vtbl.leave_meta_state(intel);
return GL_FALSE;
}
intel->vtbl.meta_texture_blend_replace( intel );
LOCK_HARDWARE( intel );
if (intel->driDrawable->numClipRects)
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
srcy = dPriv->h - srcy - height; /* convert from gl to hardware coords */
srcx += dPriv->x;
srcy += dPriv->y;
/* Clip against the source region. This is the only source
* clipping we do. XXX: Just set the texcord wrap mode to clamp
* or similar.
*
*/
if (0) {
GLint orig_x = srcx;
GLint orig_y = srcy;
if (!_mesa_clip_to_region(0, 0, src->pitch, src->height,
&srcx, &srcy, &width, &height))
goto out;
dstx += srcx - orig_x;
dsty += (srcy - orig_y) * ctx->Pixel.ZoomY;
}
/* Just use the regular cliprect mechanism... Does this need to
* even hold the lock???
*/
intel_meta_draw_quad(intel,
dstx,
dstx + width * ctx->Pixel.ZoomX,
dPriv->h - (dsty + height * ctx->Pixel.ZoomY),
dPriv->h - (dsty),
0, /* XXX: what z value? */
0x00ff00ff,
srcx, srcx+width,
srcy, srcy+height);
out:
intel->vtbl.leave_meta_state(intel);
intel_batchbuffer_flush(intel->batch);
}
UNLOCK_HARDWARE( intel );
return GL_TRUE;
}
/**
* CopyPixels with the blitter. Don't support zooming, pixel transfer, etc.
*/
static GLboolean do_blit_copypixels( GLcontext *ctx,
GLint srcx, GLint srcy,
GLsizei width, GLsizei height,
GLint dstx, GLint dsty,
GLenum type )
{
struct intel_context *intel = intel_context( ctx );
struct intel_region *dst = intel_drawbuf_region( intel );
struct intel_region *src = copypix_src_region( intel, type );
/* Copypixels can be more than a straight copy. Ensure all the
* extra operations are disabled:
*/
if (!intel_check_blit_fragment_ops(ctx) ||
ctx->Pixel.ZoomX != 1.0F ||
ctx->Pixel.ZoomY != 1.0F)
return GL_FALSE;
if (!src || !dst)
return GL_FALSE;
intelFlush( &intel->ctx );
intel->vtbl.render_start(intel);
intel->vtbl.emit_state(intel);
LOCK_HARDWARE( intel );
if (intel->driDrawable->numClipRects)
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
drm_clip_rect_t *box = dPriv->pClipRects;
drm_clip_rect_t dest_rect;
GLint nbox = dPriv->numClipRects;
GLint delta_x = 0;
GLint delta_y = 0;
GLuint i;
dsty = dPriv->h - dsty - height; /* convert from gl to hardware coords */
srcy = dPriv->h - srcy - height; /* convert from gl to hardware coords */
dstx += dPriv->x;
dsty += dPriv->y;
srcx += dPriv->x;
srcy += dPriv->y;
/* Clip against the source region. This is the only source
* clipping we do. Dst is clipped with cliprects below.
*
* TODO: Scissor?
*/
{
delta_x = srcx - dstx;
delta_y = srcy - dsty;
if (!_mesa_clip_to_region(0, 0, src->pitch, src->height,
&srcx, &srcy, &width, &height))
goto out;
dstx = srcx - delta_x;
dsty = srcy - delta_y;
}
dest_rect.x1 = dstx;
dest_rect.y1 = dsty;
dest_rect.x2 = dstx + width;
dest_rect.y2 = dsty + height;
/* Could do slightly more clipping: Eg, take the intersection of
* the existing set of cliprects and those cliprects translated
* by delta_x, delta_y:
*
* This code will not overwrite other windows, but will
* introduce garbage when copying from obscured window regions.
*/
for (i = 0 ; i < nbox ; i++ )
{
drm_clip_rect_t rect;
if (!intel_intersect_cliprects(&rect, &dest_rect, &box[i]))
continue;
intelEmitCopyBlit( intel,
dst->cpp,
src->pitch, src->buffer, 0,
dst->pitch, dst->buffer, 0,
rect.x1 + delta_x,
rect.y1 + delta_y, /* srcx, srcy */
rect.x1,
rect.y1, /* dstx, dsty */
rect.x2 - rect.x1,
rect.y2 - rect.y1 );
}
out:
intel_batchbuffer_flush( intel->batch );
}
UNLOCK_HARDWARE( intel );
return GL_TRUE;
}
void intelCopyPixels( GLcontext *ctx,
GLint srcx, GLint srcy,
GLsizei width, GLsizei height,
GLint destx, GLint desty,
GLenum type )
{
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
if (do_blit_copypixels( ctx, srcx, srcy, width, height, destx, desty, type))
return;
if (do_texture_copypixels( ctx, srcx, srcy, width, height, destx, desty, type))
return;
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("fallback to _swrast_CopyPixels\n");
_swrast_CopyPixels( ctx, srcx, srcy, width, height, destx, desty, type);
}

View file

@ -0,0 +1,365 @@
/**************************************************************************
*
* Copyright 2006 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 portionsalloc
* 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 "glheader.h"
#include "enums.h"
#include "image.h"
#include "mtypes.h"
#include "macros.h"
#include "bufferobj.h"
#include "swrast/swrast.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_regions.h"
#include "intel_pixel.h"
#include "intel_buffer_objects.h"
#include "intel_tris.h"
#include "intel_bufmgr.h"
static GLboolean do_texture_drawpixels( GLcontext *ctx,
GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels )
{
struct intel_context *intel = intel_context( ctx );
struct intel_region *dst = intel_drawbuf_region( intel );
struct intel_buffer_object *src = intel_buffer_object(unpack->BufferObj);
GLuint rowLength = unpack->RowLength ? unpack->RowLength : width;
GLuint src_offset;
if (INTEL_DEBUG & DEBUG_PIXEL)
fprintf(stderr, "%s\n", __FUNCTION__);
intelFlush( &intel->ctx );
intel->vtbl.render_start(intel);
intel->vtbl.emit_state(intel);
if (!dst)
return GL_FALSE;
if (src) {
if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
format, type, pixels)) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels");
return GL_TRUE;
}
}
else {
/* PBO only for now:
*/
/* _mesa_printf("%s - not PBO\n", __FUNCTION__); */
return GL_FALSE;
}
/* There are a couple of things we can't do yet, one of which is
* set the correct state for pixel operations when GL texturing is
* enabled. That's a pretty rare state and probably not worth the
* effort. A completely device-independent version of this may do
* more.
*
* Similarly, we make no attempt to merge metaops processing with
* an enabled fragment program, though it would certainly be
* possible.
*/
if (!intel_check_meta_tex_fragment_ops(ctx)) {
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s - bad GL fragment state for metaops texture\n", __FUNCTION__);
return GL_FALSE;
}
intel->vtbl.install_meta_state(intel);
/* Is this true? Also will need to turn depth testing on according
* to state:
*/
intel->vtbl.meta_no_stencil_write(intel);
intel->vtbl.meta_no_depth_write(intel);
/* Set the 3d engine to draw into the destination region:
*/
intel->vtbl.meta_draw_region(intel, dst, intel->depth_region);
intel->vtbl.meta_import_pixel_state(intel);
src_offset = (GLuint) _mesa_image_address(2, unpack, pixels, width, height,
format, type, 0, 0, 0);
/* Setup the pbo up as a rectangular texture, if possible.
*
* TODO: This is almost always possible if the i915 fragment
* program is adjusted to correctly swizzle the sampled colors.
* The major exception is any 24bit texture, like RGB888, for which
* there is no hardware support.
*/
if (!intel->vtbl.meta_tex_rect_source( intel, src->buffer, src_offset,
rowLength, height,
format, type )) {
intel->vtbl.leave_meta_state(intel);
return GL_FALSE;
}
intel->vtbl.meta_texture_blend_replace( intel );
LOCK_HARDWARE( intel );
if (intel->driDrawable->numClipRects)
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
GLint srcx, srcy;
GLint dstx, dsty;
dstx = x;
dsty = dPriv->h - (y + height);
srcx = 0; /* skiprows/pixels already done */
srcy = 0;
if (0) {
const GLint orig_x = dstx;
const GLint orig_y = dsty;
if (!_mesa_clip_to_region(0, 0, dst->pitch, dst->height,
&dstx, &dsty, &width, &height))
goto out;
srcx += dstx - orig_x;
srcy += dsty - orig_y;
}
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("draw %d,%d %dx%d\n", dstx,dsty,width,height);
/* Must use the regular cliprect mechanism in order to get the
* drawing origin set correctly. Otherwise scissor state is in
* incorrect coordinate space. Does this even need to hold the
* lock???
*/
intel_meta_draw_quad(intel,
dstx, dstx + width * ctx->Pixel.ZoomX,
dPriv->h - (y + height * ctx->Pixel.ZoomY),
dPriv->h - (y),
- ctx->Current.RasterPos[2] * .5,
0x00ff00ff,
srcx, srcx+width,
srcy+height, srcy);
out:
intel->vtbl.leave_meta_state(intel);
intel_batchbuffer_flush(intel->batch);
}
UNLOCK_HARDWARE( intel );
return GL_TRUE;
}
/* Pros:
* - no waiting for idle before updating framebuffer.
*
* Cons:
* - if upload is by memcpy, this may actually be slower than fallback path.
* - uploads the whole image even if destination is clipped
*
* Need to benchmark.
*
* Given the questions about performance, implement for pbo's only.
* This path is definitely a win if the pbo is already in agp. If it
* turns out otherwise, we can add the code necessary to upload client
* data to agp space before performing the blit. (Though it may turn
* out to be better/simpler just to use the texture engine).
*/
static GLboolean do_blit_drawpixels( GLcontext *ctx,
GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels )
{
struct intel_context *intel = intel_context(ctx);
struct intel_region *dest = intel_drawbuf_region(intel);
struct intel_buffer_object *src = intel_buffer_object(unpack->BufferObj);
GLuint src_offset;
GLuint rowLength;
GLuint fence = bmInitFence(intel->bm);
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s\n", __FUNCTION__);
if (!dest) {
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s - no dest\n", __FUNCTION__);
return GL_FALSE;
}
if (src) {
/* This validation should be done by core mesa:
*/
if (!_mesa_validate_pbo_access(2, unpack, 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;
}
if (!intel_check_blit_format(dest, format, type)) {
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s - bad format for blit\n", __FUNCTION__);
return GL_FALSE;
}
if (!intel_check_meta_tex_fragment_ops(ctx)) {
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s - bad GL fragment state for meta tex\n", __FUNCTION__);
return GL_FALSE;
}
if (ctx->Pixel.ZoomX != 1.0F) {
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s - bad PixelZoomX for blit\n", __FUNCTION__);
return GL_FALSE;
}
if (unpack->RowLength > 0)
rowLength = unpack->RowLength;
else
rowLength = width;
if (ctx->Pixel.ZoomY == -1.0F) {
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s - bad PixelZoomY for blit\n", __FUNCTION__);
return GL_FALSE; /* later */
y -= height;
}
else if (ctx->Pixel.ZoomY == 1.0F) {
rowLength = -rowLength;
}
else {
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s - bad PixelZoomY for blit\n", __FUNCTION__);
return GL_FALSE;
}
src_offset = (GLuint) _mesa_image_address(2, unpack, pixels, width, height,
format, type, 0, 0, 0);
intelFlush( &intel->ctx );
LOCK_HARDWARE( intel );
if (intel->driDrawable->numClipRects)
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
int nbox = dPriv->numClipRects;
drm_clip_rect_t *box = dPriv->pClipRects;
drm_clip_rect_t rect;
drm_clip_rect_t dest_rect;
int i;
dest_rect.x1 = dPriv->x + x;
dest_rect.y1 = dPriv->y + dPriv->h - (y + height);
dest_rect.x2 = dest_rect.x1 + width;
dest_rect.y2 = dest_rect.y1 + height;
for (i = 0 ; i < nbox ; i++ )
{
if (!intel_intersect_cliprects(&rect, &dest_rect, &box[i]))
continue;
intelEmitCopyBlit( intel,
dest->cpp,
rowLength,
intel_bufferobj_buffer(src), src_offset,
dest->pitch,
dest->buffer, 0,
rect.x1 - dest_rect.x1,
rect.y2 - dest_rect.y2,
rect.x1,
rect.y1,
rect.x2 - rect.x1,
rect.y2 - rect.y1 );
}
fence = intel_batchbuffer_flush( intel->batch );
}
UNLOCK_HARDWARE( intel );
if (intel->driDrawable->numClipRects)
bmFinishFence(intel->bm, fence);
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s - DONE\n", __FUNCTION__);
return GL_TRUE;
}
void intelDrawPixels( GLcontext *ctx,
GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format,
GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels )
{
if (do_blit_drawpixels( ctx, x, y, width, height, format, type,
unpack, pixels ))
return;
if (do_texture_drawpixels( ctx, x, y, width, height, format, type,
unpack, pixels ))
return;
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s: fallback to swrast\n", __FUNCTION__);
_swrast_DrawPixels( ctx, x, y, width, height, format, type,
unpack, pixels );
}

View file

@ -0,0 +1,321 @@
/**************************************************************************
*
* 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 "glheader.h"
#include "enums.h"
#include "mtypes.h"
#include "macros.h"
#include "image.h"
#include "bufferobj.h"
#include "swrast/swrast.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_regions.h"
#include "intel_pixel.h"
#include "intel_buffer_objects.h"
#include "intel_bufmgr.h"
/* 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.
*
* 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.
*
* When the destination is a pbo, however, it's not clear if it is
* ever going to be pulled to main memory (though the access param
* will be a good hint). So it sounds like we do want to be able to
* choose between blit/texture implementation on the gpu and pullback
* and cpu-based copying.
*
* Unless you can magically turn client memory into a PBO for the
* duration of this call, there will be a cpu-based copying step in
* 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,
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;
GLuint fence = bmInitFence(intel->bm);
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s\n", __FUNCTION__);
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;
}
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;
}
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->RowLength > 0)
rowLength = pack->RowLength;
else
rowLength = width;
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;
}
/* 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)
{
__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,
rowLength,
intel_bufferobj_buffer(dst), dst_offset,
rect.x1,
rect.y1,
rect.x1 - src_rect.x1,
rect.y2 - src_rect.y2,
rect.x2 - rect.x1,
rect.y2 - rect.y1 );
}
fence = intel_batchbuffer_flush(intel->batch);
}
UNLOCK_HARDWARE( intel );
if (intel->driDrawable->numClipRects)
bmFinishFence(intel->bm, fence);
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s - DONE\n", __FUNCTION__);
return GL_TRUE;
}
void
intelReadPixels( GLcontext *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__);
intelFlush( ctx );
if (do_blit_readpixels(ctx, x, y, width, height, format, type, pack, pixels))
return;
if (do_texture_readpixels(ctx, x, y, width, height, format, type, pack, pixels))
return;
if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("%s: fallback to swrast\n", __FUNCTION__);
_swrast_ReadPixels( ctx, x, y, width, height, format, type, pack, pixels);
}

View file

@ -0,0 +1,264 @@
/**************************************************************************
*
* Copyright 2006 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.
*
**************************************************************************/
/* Provide additional functionality on top of bufmgr buffers:
* - 2d semantics and blit operations
* - refcounting of buffers for multiple images in a buffer.
* - refcounting of buffer mappings.
* - some logic for moving the buffers to the best memory pools for
* given operations.
*
* Most of this is to make it easier to implement the fixed-layout
* mipmap tree required by intel hardware in the face of GL's
* programming interface where each image can be specifed in random
* order and it isn't clear what layout the tree should have until the
* last moment.
*/
#include "intel_context.h"
#include "intel_regions.h"
#include "intel_blit.h"
#include "intel_bufmgr.h"
/* XXX: Thread safety?
*/
GLubyte *intel_region_map(struct intel_context *intel, struct intel_region *region)
{
DBG("%s\n", __FUNCTION__);
if (!region->map_refcount++) {
region->map = bmMapBuffer(intel->bm, region->buffer, 0);
}
return region->map;
}
void intel_region_unmap(struct intel_context *intel,
struct intel_region *region)
{
DBG("%s\n", __FUNCTION__);
if (!--region->map_refcount) {
bmUnmapBuffer(intel->bm, region->buffer);
region->map = NULL;
}
}
struct intel_region *intel_region_alloc( struct intel_context *intel,
GLuint cpp,
GLuint pitch,
GLuint height )
{
struct intel_region *region = calloc(sizeof(*region), 1);
DBG("%s\n", __FUNCTION__);
region->cpp = cpp;
region->pitch = pitch;
region->height = height; /* needed? */
region->refcount = 1;
bmGenBuffers(intel->bm, 1, &region->buffer, 0);
bmBufferData(intel->bm, region->buffer, pitch * cpp * height, NULL, 0);
return region;
}
void intel_region_reference( struct intel_region **dst,
struct intel_region *src)
{
assert(*dst == NULL);
if (src) {
src->refcount++;
*dst = src;
}
}
void intel_region_release( struct intel_context *intel,
struct intel_region **region )
{
if (!*region)
return;
DBG("%s %d\n", __FUNCTION__, (*region)->refcount-1);
ASSERT((*region)->refcount > 0);
(*region)->refcount--;
if ((*region)->refcount == 0) {
assert((*region)->map_refcount == 0);
bmDeleteBuffers(intel->bm, 1, &(*region)->buffer);
free(*region);
}
*region = NULL;
}
struct intel_region *intel_region_create_static( struct intel_context *intel,
GLuint mem_type,
GLuint offset,
void *virtual,
GLuint cpp,
GLuint pitch,
GLuint height )
{
struct intel_region *region = calloc(sizeof(*region), 1);
DBG("%s\n", __FUNCTION__);
region->cpp = cpp;
region->pitch = pitch;
region->height = height; /* needed? */
region->refcount = 1;
/*
* We use a "shared" buffer type to indicate buffers created and
* shared by others.
*/
bmGenBuffers(intel->bm, 1, &region->buffer, DRM_MM_TT | DRM_MM_SHARED);
bmSetShared(intel->bm, region->buffer, DRM_MM_TT, offset, virtual);
return region;
}
/*
* XXX Move this into core Mesa?
*/
static void _mesa_copy_rect( GLubyte *dst,
GLuint cpp,
GLuint dst_pitch,
GLuint dst_x,
GLuint dst_y,
GLuint width,
GLuint height,
GLubyte *src,
GLuint src_pitch,
GLuint src_x,
GLuint src_y )
{
GLuint i;
dst_pitch *= cpp;
src_pitch *= cpp;
dst += dst_x * cpp;
src += src_x * cpp;
dst += dst_y * dst_pitch;
src += src_y * dst_pitch;
width *= cpp;
if (width == dst_pitch &&
width == src_pitch)
memcpy(dst, src, height * width);
else {
for (i = 0; i < height; i++) {
memcpy(dst, src, width);
dst += dst_pitch;
src += src_pitch;
}
}
}
/* Upload data to a rectangular sub-region. Lots of choices how to do this:
*
* - memcpy by span to current destination
* - upload data as new buffer and blit
*
* Currently always memcpy.
*/
void intel_region_data(struct intel_context *intel,
struct intel_region *dst,
GLuint dst_offset,
GLuint dstx, GLuint dsty,
void *src, GLuint src_pitch,
GLuint srcx, GLuint srcy,
GLuint width, GLuint height)
{
DBG("%s\n", __FUNCTION__);
LOCK_HARDWARE(intel);
_mesa_copy_rect(intel_region_map(intel, dst) + dst_offset,
dst->cpp,
dst->pitch,
dstx, dsty,
width, height,
src,
src_pitch,
srcx, srcy);
intel_region_unmap(intel, dst);
UNLOCK_HARDWARE(intel);
}
/* Copy rectangular sub-regions. Need better logic about when to
* push buffers into AGP - will currently do so whenever possible.
*/
void intel_region_copy( struct intel_context *intel,
struct intel_region *dst,
GLuint dst_offset,
GLuint dstx, GLuint dsty,
struct intel_region *src,
GLuint src_offset,
GLuint srcx, GLuint srcy,
GLuint width, GLuint height )
{
DBG("%s\n", __FUNCTION__);
assert(src->cpp == dst->cpp);
intelEmitCopyBlit(intel,
dst->cpp,
src->pitch, src->buffer, src_offset,
dst->pitch, dst->buffer, dst_offset,
srcx, srcy,
dstx, dsty,
width, height);
}
/* Fill a rectangular sub-region. Need better logic about when to
* push buffers into AGP - will currently do so whenever possible.
*/
void intel_region_fill( struct intel_context *intel,
struct intel_region *dst,
GLuint dst_offset,
GLuint dstx, GLuint dsty,
GLuint width, GLuint height,
GLuint color )
{
DBG("%s\n", __FUNCTION__);
intelEmitFillBlit(intel,
dst->cpp,
dst->pitch, dst->buffer, dst_offset,
dstx, dsty,
width, height,
color );
}

View file

@ -0,0 +1,119 @@
/**************************************************************************
*
* Copyright 2006 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.
*
**************************************************************************/
#ifndef INTEL_REGIONS_H
#define INTEL_REGIONS_H
#include "mtypes.h"
#include "intel_bufmgr.h" /* for DBG! */
struct intel_context;
/**
* A layer on top of the bufmgr buffers that adds a few useful things:
*
* - Refcounting for local buffer references.
* - Refcounting for buffer maps
* - Buffer dimensions - pitch and height.
* - Blitter commands for copying 2D regions between buffers. (really???)
*/
struct intel_region {
GLuint buffer; /**< buffer manager's buffer ID */
GLuint refcount; /**< Reference count for region */
GLuint cpp; /**< bytes per pixel */
GLuint pitch; /**< in pixels */
GLuint height; /**< in pixels */
GLubyte *map; /**< only non-NULL when region is actually mapped */
GLuint map_refcount; /**< Reference count for mapping */
GLuint draw_offset; /**< Offset of drawing address within the region */
};
/* Allocate a refcounted region. Pointers to regions should only be
* copied by calling intel_reference_region().
*/
struct intel_region *intel_region_alloc( struct intel_context *intel,
GLuint cpp,
GLuint pitch,
GLuint height );
void intel_region_reference( struct intel_region **dst,
struct intel_region *src );
void intel_region_release(struct intel_context *intel,
struct intel_region **ib );
struct intel_region *intel_region_create_static( struct intel_context *intel,
GLuint mem_type,
GLuint offset,
void *virtual,
GLuint cpp,
GLuint pitch,
GLuint height );
/* Map/unmap regions. This is refcounted also:
*/
GLubyte *intel_region_map(struct intel_context *intel,
struct intel_region *ib);
void intel_region_unmap(struct intel_context *intel,
struct intel_region *ib);
/* Upload data to a rectangular sub-region
*/
void intel_region_data(struct intel_context *intel,
struct intel_region *dest,
GLuint dest_offset,
GLuint destx, GLuint desty,
void *src, GLuint src_stride,
GLuint srcx, GLuint srcy,
GLuint width, GLuint height);
/* Copy rectangular sub-regions
*/
void intel_region_copy( struct intel_context *intel,
struct intel_region *dest,
GLuint dest_offset,
GLuint destx, GLuint desty,
struct intel_region *src,
GLuint src_offset,
GLuint srcx, GLuint srcy,
GLuint width, GLuint height );
/* Fill a rectangular sub-region
*/
void intel_region_fill( struct intel_context *intel,
struct intel_region *dest,
GLuint dest_offset,
GLuint destx, GLuint desty,
GLuint width, GLuint height,
GLuint color );
#endif

View file

@ -0,0 +1,296 @@
/**************************************************************************
*
* 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 "mtypes.h"
#include "enums.h"
#include "image.h"
#include "teximage.h"
#include "swrast/swrast.h"
#include "intel_screen.h"
#include "intel_context.h"
#include "intel_batchbuffer.h"
#include "intel_buffers.h"
#include "intel_mipmap_tree.h"
#include "intel_regions.h"
#include "intel_fbo.h"
#include "intel_tex.h"
#include "intel_blit.h"
#include "intel_pixel.h"
#include "intel_bufmgr.h"
/**
* Get the intel_region which is the source for any glCopyTex[Sub]Image call.
*
* Do the best we can using the blitter. A future project is to use
* the texture engine and fragment programs for these copies.
*/
static const struct intel_region *
get_teximage_source(struct intel_context *intel, GLenum internalFormat)
{
struct intel_renderbuffer *irb;
if (0)
_mesa_printf("%s %s\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(internalFormat));
switch (internalFormat) {
case GL_DEPTH_COMPONENT:
case GL_DEPTH_COMPONENT16_ARB:
irb = intel_get_renderbuffer(intel->ctx.ReadBuffer, BUFFER_DEPTH);
if (irb && irb->region && irb->region->cpp == 2)
return irb->region;
return NULL;
case GL_DEPTH24_STENCIL8_EXT:
case GL_DEPTH_STENCIL_EXT:
irb = intel_get_renderbuffer(intel->ctx.ReadBuffer, BUFFER_DEPTH);
if (irb && irb->region && irb->region->cpp == 4)
return irb->region;
return NULL;
case GL_RGBA:
return intel_readbuf_region( intel );
case GL_RGB:
if (intel->intelScreen->cpp == 2)
return intel_readbuf_region( intel );
return NULL;
default:
return NULL;
}
}
static GLboolean do_copy_texsubimage( struct intel_context *intel,
struct intel_texture_image *intelImage,
GLenum internalFormat,
GLint dstx, GLint dsty,
GLint x, GLint y,
GLsizei width, GLsizei height )
{
GLcontext *ctx = &intel->ctx;
const struct intel_region *src = get_teximage_source(intel, internalFormat);
if (!intelImage->mt || !src)
return GL_FALSE;
intelFlush(ctx);
LOCK_HARDWARE(intel);
{
GLuint image_offset = intel_miptree_image_offset(intelImage->mt,
intelImage->face,
intelImage->level);
const GLint orig_x = x;
const GLint orig_y = y;
const struct gl_framebuffer *fb = ctx->DrawBuffer;
if (_mesa_clip_to_region(fb->_Xmin, fb->_Ymin, fb->_Xmax, fb->_Ymax,
&x, &y, &width, &height)) {
/* Update dst for clipped src. Need to also clip the source rect.
*/
dstx += x - orig_x;
dsty += y - orig_y;
if (ctx->ReadBuffer->Name == 0) {
/* reading from a window, adjust x, y */
__DRIdrawablePrivate *dPriv = intel->driDrawable;
GLuint window_y;
/* window_y = position of window on screen if y=0=bottom */
window_y = intel->intelScreen->height - (dPriv->y + dPriv->h);
y = window_y + y;
x += dPriv->x;
}
else {
/* reading from a FBO */
/* invert Y */
y = ctx->ReadBuffer->Height - y - 1;
}
/* A bit of fiddling to get the blitter to work with -ve
* pitches. But we get a nice inverted blit this way, so it's
* worth it:
*/
intelEmitCopyBlit( intel,
intelImage->mt->cpp,
-src->pitch,
src->buffer,
src->height * src->pitch * src->cpp,
intelImage->mt->pitch,
intelImage->mt->region->buffer,
image_offset,
x, y + height,
dstx, dsty,
width, height );
intel_batchbuffer_flush( intel->batch );
}
}
UNLOCK_HARDWARE(intel);
#if 0
/* GL_SGIS_generate_mipmap -- this can be accelerated now.
* XXX Add a ctx->Driver.GenerateMipmaps() function?
*/
if (level == texObj->BaseLevel &&
texObj->GenerateMipmap) {
intel_generate_mipmap(ctx, target,
&ctx->Texture.Unit[ctx->Texture.CurrentUnit],
texObj);
}
#endif
return GL_TRUE;
}
void intelCopyTexImage1D( GLcontext *ctx, GLenum target, GLint level,
GLenum internalFormat,
GLint x, GLint y, GLsizei width,
GLint border )
{
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
struct gl_texture_object *texObj = _mesa_select_tex_object(ctx, texUnit, target);
struct gl_texture_image *texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
if (border)
goto fail;
/* Setup or redefine the texture object, mipmap tree and texture
* image. Don't populate yet.
*/
ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
width, border,
GL_RGBA, CHAN_TYPE, NULL,
&ctx->DefaultPacking, texObj, texImage);
if (!do_copy_texsubimage(intel_context(ctx),
intel_texture_image(texImage),
internalFormat,
0, 0,
x, y,
width, 1))
goto fail;
return;
fail:
_swrast_copy_teximage1d( ctx, target, level, internalFormat, x, y,
width, border );
}
void intelCopyTexImage2D( GLcontext *ctx, GLenum target, GLint level,
GLenum internalFormat,
GLint x, GLint y, GLsizei width, GLsizei height,
GLint border )
{
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
struct gl_texture_object *texObj = _mesa_select_tex_object(ctx, texUnit, target);
struct gl_texture_image *texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
if (border)
goto fail;
/* Setup or redefine the texture object, mipmap tree and texture
* image. Don't populate yet.
*/
ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
width, height, border,
GL_RGBA, CHAN_TYPE, NULL,
&ctx->DefaultPacking, texObj, texImage);
if (!do_copy_texsubimage(intel_context(ctx),
intel_texture_image(texImage),
internalFormat,
0, 0,
x, y,
width, height))
goto fail;
return;
fail:
_swrast_copy_teximage2d( ctx, target, level, internalFormat, x, y,
width, height, border );
}
void intelCopyTexSubImage1D( GLcontext *ctx, GLenum target, GLint level,
GLint xoffset,
GLint x, GLint y, GLsizei width )
{
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
struct gl_texture_image *texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
GLenum internalFormat = texImage->InternalFormat;
/* XXX need to check <border> as in above function? */
/* Need to check texture is compatible with source format.
*/
if (!do_copy_texsubimage(intel_context(ctx),
intel_texture_image(texImage),
internalFormat,
xoffset, 0,
x, y, width, 1)) {
_swrast_copy_texsubimage1d( ctx, target, level,
xoffset, x, y, width );
}
}
void intelCopyTexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
GLint xoffset, GLint yoffset,
GLint x, GLint y, GLsizei width, GLsizei height )
{
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
struct gl_texture_image *texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
GLenum internalFormat = texImage->InternalFormat;
/* Need to check texture is compatible with source format.
*/
if (!do_copy_texsubimage(intel_context(ctx),
intel_texture_image(texImage),
internalFormat,
xoffset, yoffset,
x, y, width, height)) {
_swrast_copy_texsubimage2d( ctx, target, level,
xoffset, yoffset,
x, y, width, height );
}
}

View file

@ -0,0 +1,148 @@
#include "intel_context.h"
#include "intel_tex.h"
#include "texformat.h"
#include "enums.h"
/* It works out that this function is fine for all the supported
* hardware. However, there is still a need to map the formats onto
* hardware descriptors.
*/
/* Note that the i915 can actually support many more formats than
* these if we take the step of simply swizzling the colors
* immediately after sampling...
*/
const struct gl_texture_format *
intelChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
GLenum format, GLenum type )
{
struct intel_context *intel = intel_context( ctx );
const GLboolean do32bpt = (intel->intelScreen->cpp == 4);
switch ( internalFormat ) {
case 4:
case GL_RGBA:
case GL_COMPRESSED_RGBA:
if ( format == GL_BGRA ) {
if ( type == GL_UNSIGNED_INT_8_8_8_8_REV ) {
return &_mesa_texformat_argb8888;
}
else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
return &_mesa_texformat_argb4444;
}
else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
return &_mesa_texformat_argb1555;
}
}
return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
case 3:
case GL_RGB:
case GL_COMPRESSED_RGB:
if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
return &_mesa_texformat_rgb565;
}
return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
case GL_RGBA8:
case GL_RGB10_A2:
case GL_RGBA12:
case GL_RGBA16:
return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
case GL_RGBA4:
case GL_RGBA2:
return &_mesa_texformat_argb4444;
case GL_RGB5_A1:
return &_mesa_texformat_argb1555;
case GL_RGB8:
case GL_RGB10:
case GL_RGB12:
case GL_RGB16:
return &_mesa_texformat_argb8888;
case GL_RGB5:
case GL_RGB4:
case GL_R3_G3_B2:
return &_mesa_texformat_rgb565;
case GL_ALPHA:
case GL_ALPHA4:
case GL_ALPHA8:
case GL_ALPHA12:
case GL_ALPHA16:
case GL_COMPRESSED_ALPHA:
return &_mesa_texformat_a8;
case 1:
case GL_LUMINANCE:
case GL_LUMINANCE4:
case GL_LUMINANCE8:
case GL_LUMINANCE12:
case GL_LUMINANCE16:
case GL_COMPRESSED_LUMINANCE:
return &_mesa_texformat_l8;
case 2:
case GL_LUMINANCE_ALPHA:
case GL_LUMINANCE4_ALPHA4:
case GL_LUMINANCE6_ALPHA2:
case GL_LUMINANCE8_ALPHA8:
case GL_LUMINANCE12_ALPHA4:
case GL_LUMINANCE12_ALPHA12:
case GL_LUMINANCE16_ALPHA16:
case GL_COMPRESSED_LUMINANCE_ALPHA:
return &_mesa_texformat_al88;
case GL_INTENSITY:
case GL_INTENSITY4:
case GL_INTENSITY8:
case GL_INTENSITY12:
case GL_INTENSITY16:
case GL_COMPRESSED_INTENSITY:
return &_mesa_texformat_i8;
case GL_YCBCR_MESA:
if (type == GL_UNSIGNED_SHORT_8_8_MESA ||
type == GL_UNSIGNED_BYTE)
return &_mesa_texformat_ycbcr;
else
return &_mesa_texformat_ycbcr_rev;
case GL_COMPRESSED_RGB_FXT1_3DFX:
return &_mesa_texformat_rgb_fxt1;
case GL_COMPRESSED_RGBA_FXT1_3DFX:
return &_mesa_texformat_rgba_fxt1;
case GL_RGB_S3TC:
case GL_RGB4_S3TC:
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
return &_mesa_texformat_rgb_dxt1;
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
return &_mesa_texformat_rgba_dxt1;
case GL_RGBA_S3TC:
case GL_RGBA4_S3TC:
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
return &_mesa_texformat_rgba_dxt3;
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
return &_mesa_texformat_rgba_dxt5;
case GL_DEPTH_COMPONENT:
case GL_DEPTH_COMPONENT16:
case GL_DEPTH_COMPONENT24:
case GL_DEPTH_COMPONENT32:
return &_mesa_texformat_z16;
default:
fprintf(stderr, "unexpected texture format %s in %s\n",
_mesa_lookup_enum_by_nr(internalFormat),
__FUNCTION__);
return NULL;
}
return NULL; /* never get here */
}

View file

@ -0,0 +1,179 @@
/**************************************************************************
*
* 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 "mtypes.h"
#include "texobj.h"
#include "texstore.h"
#include "enums.h"
#include "intel_context.h"
#include "intel_tex.h"
#include "intel_mipmap_tree.h"
static void intelTexSubimage (GLcontext *ctx,
GLint dims,
GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLint width, GLint height, GLint depth,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
struct intel_context *intel = intel_context(ctx);
struct intel_texture_image *intelImage = intel_texture_image(texImage);
GLuint dstImageStride;
GLuint dstRowStride;
DBG("%s target %s level %d offset %d,%d %dx%d\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(target),
level,
xoffset, yoffset,
width, height);
intelFlush(ctx);
pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, depth, format, type,
pixels, packing, "glTexSubImage2D");
if (!pixels)
return;
LOCK_HARDWARE(intel);
/* Map buffer if necessary. Need to lock to prevent other contexts
* from uploading the buffer under us.
*/
if (intelImage->mt)
texImage->Data = intel_miptree_image_map(intel,
intelImage->mt,
intelImage->face,
intelImage->level,
&dstRowStride,
&dstImageStride );
assert(dstRowStride);
if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat,
texImage->TexFormat,
texImage->Data,
xoffset, yoffset, zoffset,
dstRowStride,
texImage->ImageOffsets,
width, height, depth,
format, type, pixels, packing)) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "intelTexSubImage");
}
#if 0
/* GL_SGIS_generate_mipmap */
if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
_mesa_generate_mipmap(ctx, target,
&ctx->Texture.Unit[ctx->Texture.CurrentUnit],
texObj);
}
#endif
_mesa_unmap_teximage_pbo(ctx, packing);
if (intelImage->mt) {
intel_miptree_image_unmap(intel, intelImage->mt);
texImage->Data = NULL;
}
UNLOCK_HARDWARE(intel);
}
void intelTexSubImage3D(GLcontext *ctx,
GLenum target,
GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
intelTexSubimage(ctx, 3,
target, level,
xoffset, yoffset, zoffset,
width, height, depth,
format, type, pixels, packing, texObj,
texImage);
}
void intelTexSubImage2D(GLcontext *ctx,
GLenum target,
GLint level,
GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
intelTexSubimage(ctx, 2,
target, level,
xoffset, yoffset, 0,
width, height, 1,
format, type, pixels, packing, texObj,
texImage);
}
void intelTexSubImage1D(GLcontext *ctx,
GLenum target,
GLint level,
GLint xoffset,
GLsizei width,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
intelTexSubimage(ctx, 1,
target, level,
xoffset, 0, 0,
width, 1, 1,
format, type, pixels, packing, texObj,
texImage);
}

View file

@ -0,0 +1,247 @@
#include "mtypes.h"
#include "macros.h"
#include "intel_context.h"
#include "intel_mipmap_tree.h"
#include "intel_tex.h"
#include "intel_bufmgr.h"
/**
* Compute which mipmap levels that really need to be sent to the hardware.
* This depends on the base image size, GL_TEXTURE_MIN_LOD,
* GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
*/
static void intel_calculate_first_last_level( struct intel_texture_object *intelObj )
{
struct gl_texture_object *tObj = &intelObj->base;
const struct gl_texture_image * const baseImage =
tObj->Image[0][tObj->BaseLevel];
/* These must be signed values. MinLod and MaxLod can be negative numbers,
* and having firstLevel and lastLevel as signed prevents the need for
* extra sign checks.
*/
int firstLevel;
int lastLevel;
/* Yes, this looks overly complicated, but it's all needed.
*/
switch (tObj->Target) {
case GL_TEXTURE_1D:
case GL_TEXTURE_2D:
case GL_TEXTURE_3D:
case GL_TEXTURE_CUBE_MAP:
if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
/* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
*/
firstLevel = lastLevel = tObj->BaseLevel;
}
else {
firstLevel = tObj->BaseLevel + (GLint)(tObj->MinLod + 0.5);
firstLevel = MAX2(firstLevel, tObj->BaseLevel);
lastLevel = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5);
lastLevel = MAX2(lastLevel, tObj->BaseLevel);
lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
lastLevel = MIN2(lastLevel, tObj->MaxLevel);
lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
}
break;
case GL_TEXTURE_RECTANGLE_NV:
case GL_TEXTURE_4D_SGIS:
firstLevel = lastLevel = 0;
break;
default:
return;
}
/* save these values */
intelObj->firstLevel = firstLevel;
intelObj->lastLevel = lastLevel;
}
static void copy_image_data_to_tree( struct intel_context *intel,
struct intel_texture_object *intelObj,
struct intel_texture_image *intelImage )
{
if (intelImage->mt) {
/* Copy potentially with the blitter:
*/
intel_miptree_image_copy(intel,
intelObj->mt,
intelImage->face,
intelImage->level,
intelImage->mt);
intel_miptree_release(intel, &intelImage->mt);
}
else {
assert(intelImage->base.Data != NULL);
/* More straightforward upload.
*/
intel_miptree_image_data(intel,
intelObj->mt,
intelImage->face,
intelImage->level,
intelImage->base.Data,
intelImage->base.RowStride,
intelImage->base.RowStride * intelImage->base.Height);
free(intelImage->base.Data);
intelImage->base.Data = NULL;
}
intel_miptree_reference(&intelImage->mt, intelObj->mt);
}
/*
*/
GLuint intel_finalize_mipmap_tree( struct intel_context *intel, GLuint unit )
{
struct gl_texture_object *tObj = intel->ctx.Texture.Unit[unit]._Current;
struct intel_texture_object *intelObj = intel_texture_object(tObj);
GLuint face, i;
GLuint nr_faces = 0;
struct intel_texture_image *firstImage;
/* We know/require this is true by now:
*/
assert(intelObj->base.Complete);
/* What levels must the tree include at a minimum?
*/
intel_calculate_first_last_level( intelObj );
firstImage = intel_texture_image(intelObj->base.Image[0][intelObj->firstLevel]);
/* Fallback case:
*/
if (firstImage->base.Border) {
if (intelObj->mt) {
intel_miptree_release(intel, &intelObj->mt);
}
return GL_FALSE;
}
/* If both firstImage and intelObj have a tree which can contain
* all active images, favour firstImage. Note that because of the
* completeness requirement, we know that the image dimensions
* will match.
*/
if (firstImage->mt &&
firstImage->mt != intelObj->mt &&
firstImage->mt->first_level <= intelObj->firstLevel &&
firstImage->mt->last_level >= intelObj->lastLevel) {
if (intelObj->mt)
intel_miptree_release(intel, &intelObj->mt);
intel_miptree_reference(&intelObj->mt, firstImage->mt);
}
/* Check tree can hold all active levels. Check tree matches
* target, imageFormat, etc.
*
* XXX: For some layouts (eg i945?), the test might have to be
* first_level == firstLevel, as the tree isn't valid except at the
* original start level. Hope to get around this by
* programming minLod, maxLod, baseLevel into the hardware and
* leaving the tree alone.
*/
if (intelObj->mt &&
((intelObj->mt->first_level > intelObj->firstLevel) ||
(intelObj->mt->last_level < intelObj->lastLevel) ||
(intelObj->mt->internal_format != firstImage->base.InternalFormat))) {
intel_miptree_release(intel, &intelObj->mt);
}
/* May need to create a new tree:
*/
if (!intelObj->mt) {
intelObj->mt = intel_miptree_create(intel,
intelObj->base.Target,
firstImage->base.InternalFormat,
intelObj->firstLevel,
intelObj->lastLevel,
firstImage->base.Width,
firstImage->base.Height,
firstImage->base.Depth,
firstImage->base.TexFormat->TexelBytes,
firstImage->base.IsCompressed);
}
/* Pull in any images not in the object's tree:
*/
nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
for (face = 0; face < nr_faces; face++) {
for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) {
struct intel_texture_image *intelImage =
intel_texture_image(intelObj->base.Image[face][i]);
/* Need to import images in main memory or held in other trees.
*/
if (intelObj->mt != intelImage->mt) {
copy_image_data_to_tree(intel,
intelObj,
intelImage);
}
}
}
return GL_TRUE;
}
void intel_tex_map_images( struct intel_context *intel,
struct intel_texture_object *intelObj )
{
GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
GLuint face, i;
DBG("%s\n", __FUNCTION__);
for (face = 0; face < nr_faces; face++) {
for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) {
struct intel_texture_image *intelImage =
intel_texture_image(intelObj->base.Image[face][i]);
if (intelImage->mt) {
intelImage->base.Data =
intel_miptree_image_map(intel,
intelImage->mt,
intelImage->face,
intelImage->level,
&intelImage->base.RowStride,
intelImage->base.ImageOffsets);
/* convert stride to texels, not bytes */
intelImage->base.RowStride /= intelImage->mt->cpp;
/* intelImage->base.ImageStride /= intelImage->mt->cpp; */
}
}
}
}
void intel_tex_unmap_images( struct intel_context *intel,
struct intel_texture_object *intelObj )
{
GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
GLuint face, i;
for (face = 0; face < nr_faces; face++) {
for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) {
struct intel_texture_image *intelImage =
intel_texture_image(intelObj->base.Image[face][i]);
if (intelImage->mt) {
intel_miptree_image_unmap(intel, intelImage->mt);
intelImage->base.Data = NULL;
}
}
}
}