mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-09 08:58:02 +02:00
new files from merge of texmem driver
This commit is contained in:
parent
527c05eb2a
commit
ded29089f3
22 changed files with 5396 additions and 0 deletions
62
src/mesa/drivers/dri/i915/intel_blit.h
Normal file
62
src/mesa/drivers/dri/i915/intel_blit.h
Normal 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
|
||||
201
src/mesa/drivers/dri/i915/intel_buffer_objects.c
Normal file
201
src/mesa/drivers/dri/i915/intel_buffer_objects.c
Normal 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;
|
||||
}
|
||||
70
src/mesa/drivers/dri/i915/intel_buffer_objects.h
Normal file
70
src/mesa/drivers/dri/i915/intel_buffer_objects.h
Normal 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
|
||||
947
src/mesa/drivers/dri/i915/intel_buffers.c
Normal file
947
src/mesa/drivers/dri/i915/intel_buffers.c
Normal 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;
|
||||
}
|
||||
63
src/mesa/drivers/dri/i915/intel_buffers.h
Normal file
63
src/mesa/drivers/dri/i915/intel_buffers.h
Normal 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 */
|
||||
132
src/mesa/drivers/dri/i915/intel_bufmgr.h
Normal file
132
src/mesa/drivers/dri/i915/intel_bufmgr.h
Normal 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
|
||||
281
src/mesa/drivers/dri/i915/intel_depthstencil.c
Normal file
281
src/mesa/drivers/dri/i915/intel_depthstencil.c
Normal 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.
|
||||
*/
|
||||
}
|
||||
13
src/mesa/drivers/dri/i915/intel_depthstencil.h
Normal file
13
src/mesa/drivers/dri/i915/intel_depthstencil.h
Normal 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 */
|
||||
639
src/mesa/drivers/dri/i915/intel_fbo.c
Normal file
639
src/mesa/drivers/dri/i915/intel_fbo.c
Normal 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;
|
||||
}
|
||||
75
src/mesa/drivers/dri/i915/intel_fbo.h
Normal file
75
src/mesa/drivers/dri/i915/intel_fbo.h
Normal 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 */
|
||||
359
src/mesa/drivers/dri/i915/intel_mipmap_tree.c
Normal file
359
src/mesa/drivers/dri/i915/intel_mipmap_tree.c
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
201
src/mesa/drivers/dri/i915/intel_mipmap_tree.h
Normal file
201
src/mesa/drivers/dri/i915/intel_mipmap_tree.h
Normal 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
|
||||
64
src/mesa/drivers/dri/i915/intel_pixel.h
Normal file
64
src/mesa/drivers/dri/i915/intel_pixel.h
Normal 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
|
||||
350
src/mesa/drivers/dri/i915/intel_pixel_copy.c
Normal file
350
src/mesa/drivers/dri/i915/intel_pixel_copy.c
Normal 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);
|
||||
}
|
||||
|
||||
|
||||
365
src/mesa/drivers/dri/i915/intel_pixel_draw.c
Normal file
365
src/mesa/drivers/dri/i915/intel_pixel_draw.c
Normal 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 );
|
||||
}
|
||||
|
||||
321
src/mesa/drivers/dri/i915/intel_pixel_read.c
Normal file
321
src/mesa/drivers/dri/i915/intel_pixel_read.c
Normal 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);
|
||||
}
|
||||
|
||||
264
src/mesa/drivers/dri/i915/intel_regions.c
Normal file
264
src/mesa/drivers/dri/i915/intel_regions.c
Normal 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, ®ion->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, ®ion->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 );
|
||||
}
|
||||
|
||||
119
src/mesa/drivers/dri/i915/intel_regions.h
Normal file
119
src/mesa/drivers/dri/i915/intel_regions.h
Normal 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
|
||||
296
src/mesa/drivers/dri/i915/intel_tex_copy.c
Normal file
296
src/mesa/drivers/dri/i915/intel_tex_copy.c
Normal 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 );
|
||||
}
|
||||
}
|
||||
148
src/mesa/drivers/dri/i915/intel_tex_format.c
Normal file
148
src/mesa/drivers/dri/i915/intel_tex_format.c
Normal 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 */
|
||||
}
|
||||
179
src/mesa/drivers/dri/i915/intel_tex_subimage.c
Normal file
179
src/mesa/drivers/dri/i915/intel_tex_subimage.c
Normal 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);
|
||||
|
||||
}
|
||||
247
src/mesa/drivers/dri/i915/intel_tex_validate.c
Normal file
247
src/mesa/drivers/dri/i915/intel_tex_validate.c
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue