dri/nouveau: Implement EXT_texture_from_pixmap.

This commit is contained in:
Francisco Jerez
2010-02-21 14:23:40 +01:00
parent a7b8d105a6
commit 4a7e9b5df4
7 changed files with 116 additions and 57 deletions
+46 -45
View File
@@ -168,19 +168,19 @@ nouveau_context_destroy(__DRIcontext *dri_ctx)
context_drv(ctx)->context_destroy(ctx);
}
static void
nouveau_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable,
unsigned int *stamp)
void
nouveau_update_renderbuffers(__DRIcontext *dri_ctx, __DRIdrawable *draw)
{
struct nouveau_context *nctx = context->driverPrivate;
GLcontext *ctx = &nctx->base;
__DRIscreen *screen = context->driScreenPriv;
struct gl_framebuffer *fb = drawable->driverPrivate;
GLcontext *ctx = dri_ctx->driverPrivate;
__DRIscreen *screen = dri_ctx->driScreenPriv;
struct gl_framebuffer *fb = draw->driverPrivate;
unsigned int attachments[10];
__DRIbuffer *buffers = NULL;
int i = 0, count, ret;
*stamp = *drawable->pStamp;
if (draw->lastStamp == *draw->pStamp)
return;
draw->lastStamp = *draw->pStamp;
attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
if (fb->Visual.doubleBufferMode)
@@ -192,10 +192,9 @@ nouveau_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable,
else if (fb->Visual.haveStencilBuffer)
attachments[i++] = __DRI_BUFFER_STENCIL;
buffers = (*screen->dri2.loader->getBuffers)(drawable,
&drawable->w, &drawable->h,
buffers = (*screen->dri2.loader->getBuffers)(draw, &draw->w, &draw->h,
attachments, i, &count,
drawable->loaderPrivate);
draw->loaderPrivate);
if (buffers == NULL)
return;
@@ -227,8 +226,8 @@ nouveau_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable,
rb = fb->Attachment[index].Renderbuffer;
s = &to_nouveau_renderbuffer(rb)->surface;
s->width = drawable->w;
s->height = drawable->h;
s->width = draw->w;
s->height = draw->h;
s->pitch = buffers[i].pitch;
s->cpp = buffers[i].cpp;
@@ -244,12 +243,25 @@ nouveau_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable,
ret = nouveau_bo_handle_ref(context_dev(ctx),
buffers[i].name, &s->bo);
assert(!ret);
context_dirty(ctx, FRAMEBUFFER);
}
}
_mesa_resize_framebuffer(ctx, fb, drawable->w, drawable->h);
_mesa_resize_framebuffer(NULL, fb, draw->w, draw->h);
}
static void
update_framebuffer(__DRIcontext *dri_ctx, __DRIdrawable *draw,
int *stamp)
{
GLcontext *ctx = dri_ctx->driverPrivate;
struct gl_framebuffer *fb = draw->driverPrivate;
*stamp = *draw->pStamp;
nouveau_update_renderbuffers(dri_ctx, draw);
_mesa_resize_framebuffer(ctx, fb, draw->w, draw->h);
context_dirty(ctx, FRAMEBUFFER);
}
GLboolean
@@ -260,16 +272,15 @@ nouveau_context_make_current(__DRIcontext *dri_ctx, __DRIdrawable *dri_draw,
struct nouveau_context *nctx = dri_ctx->driverPrivate;
GLcontext *ctx = &nctx->base;
if (dri_draw->driverPrivate == ctx->WinSysDrawBuffer &&
dri_read->driverPrivate == ctx->WinSysReadBuffer)
return GL_TRUE;
/* Ask the X server for new renderbuffers. */
nouveau_update_renderbuffers(dri_ctx, dri_draw,
&nctx->drawable.d_stamp);
if (dri_draw != dri_read)
nouveau_update_renderbuffers(dri_ctx, dri_read,
&nctx->drawable.r_stamp);
if (dri_draw->driverPrivate != ctx->WinSysDrawBuffer)
update_framebuffer(dri_ctx, dri_draw,
&dri_ctx->dri2.draw_stamp);
if (dri_draw != dri_read &&
dri_read->driverPrivate != ctx->WinSysReadBuffer)
update_framebuffer(dri_ctx, dri_read,
&dri_ctx->dri2.read_stamp);
/* Pass it down to mesa. */
_mesa_make_current(ctx, dri_draw->driverPrivate,
@@ -307,30 +318,20 @@ nouveau_fallback(GLcontext *ctx, enum nouveau_fallback mode)
void
nouveau_validate_framebuffer(GLcontext *ctx)
{
struct nouveau_context *nctx = to_nouveau_context(ctx);
__DRIcontext *dri_ctx = to_nouveau_context(ctx)->dri_context;
__DRIdrawable *dri_draw = dri_ctx->driDrawablePriv;
__DRIdrawable *dri_read = dri_ctx->driReadablePriv;
if ((ctx->DrawBuffer->Name == 0 &&
nctx->drawable.d_stamp != *dri_draw->pStamp) ||
(dri_draw != dri_read &&
ctx->ReadBuffer->Name == 0 &&
nctx->drawable.r_stamp != *dri_read->pStamp)) {
if (nctx->drawable.dirty)
ctx->Driver.Flush(ctx);
if (ctx->DrawBuffer->Name == 0 &&
dri_ctx->dri2.draw_stamp != *dri_draw->pStamp)
update_framebuffer(dri_ctx, dri_draw,
&dri_ctx->dri2.draw_stamp);
/* Ask the X server for new renderbuffers. */
nouveau_update_renderbuffers(dri_ctx, dri_draw,
&nctx->drawable.d_stamp);
if (dri_draw != dri_read)
nouveau_update_renderbuffers(dri_ctx, dri_read,
&nctx->drawable.r_stamp);
if (ctx->ReadBuffer->Name == 0 && dri_draw != dri_read &&
dri_ctx->dri2.read_stamp != *dri_read->pStamp)
update_framebuffer(dri_ctx, dri_read,
&dri_ctx->dri2.read_stamp);
if (nouveau_next_dirty_state(ctx) >= 0)
FIRE_RING(context_chan(ctx));
}
/* Someone's planning to draw something really soon. */
nctx->drawable.dirty = GL_TRUE;
if (nouveau_next_dirty_state(ctx) >= 0)
FIRE_RING(context_chan(ctx));
}
@@ -56,12 +56,6 @@ struct nouveau_hw_state {
struct nouveau_grobj *sifm;
};
struct nouveau_drawable_state {
GLboolean dirty;
unsigned int d_stamp;
unsigned int r_stamp;
};
struct nouveau_context {
GLcontext base;
__DRIcontext *dri_context;
@@ -73,7 +67,6 @@ struct nouveau_context {
struct nouveau_hw_state hw;
struct nouveau_bo_state bo;
struct nouveau_render_state render;
struct nouveau_drawable_state drawable;
};
#define to_nouveau_context(ctx) ((struct nouveau_context *)(ctx))
@@ -107,9 +100,11 @@ nouveau_context_deinit(GLcontext *ctx);
void
nouveau_context_destroy(__DRIcontext *dri_ctx);
void
nouveau_update_renderbuffers(__DRIcontext *dri_ctx, __DRIdrawable *draw);
GLboolean
nouveau_context_make_current(__DRIcontext *dri_ctx,
__DRIdrawable *ddraw,
nouveau_context_make_current(__DRIcontext *dri_ctx, __DRIdrawable *ddraw,
__DRIdrawable *rdraw);
GLboolean
@@ -67,8 +67,6 @@ nouveau_flush(GLcontext *ctx)
dri2->flushFrontBuffer(drawable, drawable->loaderPrivate);
}
nctx->drawable.dirty = GL_FALSE;
}
static void
@@ -142,7 +142,6 @@ nouveau_renderbuffer_dri_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
rb->Width = width;
rb->Height = height;
context_dirty(ctx, FRAMEBUFFER);
return GL_TRUE;
}
@@ -27,6 +27,7 @@
#include "nouveau_driver.h"
#include "nouveau_context.h"
#include "nouveau_fbo.h"
#include "nouveau_texture.h"
#include "nouveau_drmif.h"
#include "nv04_driver.h"
#include "nv10_driver.h"
@@ -226,8 +227,15 @@ static const struct __DRI2flushExtensionRec nouveau_flush_extension = {
dri2InvalidateDrawable,
};
static const struct __DRItexBufferExtensionRec nouveau_texbuffer_extension = {
{ __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION },
NULL,
nouveau_set_texbuffer,
};
static const __DRIextension *nouveau_screen_extensions[] = {
&nouveau_flush_extension.base,
&nouveau_texbuffer_extension.base,
NULL
};
@@ -27,6 +27,7 @@
#include "nouveau_driver.h"
#include "nouveau_context.h"
#include "nouveau_texture.h"
#include "nouveau_fbo.h"
#include "nouveau_util.h"
#include "main/texobj.h"
@@ -36,6 +37,7 @@
#include "main/texgetimage.h"
#include "main/mipmap.h"
#include "main/texfetch.h"
#include "main/teximage.h"
static struct gl_texture_object *
nouveau_texture_new(GLcontext *ctx, GLuint name, GLenum target)
@@ -489,6 +491,57 @@ nouveau_bind_texture(GLcontext *ctx, GLenum target,
context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
}
static gl_format
get_texbuffer_format(struct gl_renderbuffer *rb, GLint format)
{
struct nouveau_surface *s = &to_nouveau_renderbuffer(rb)->surface;
if (s->cpp < 4)
return s->format;
else if (format == __DRI_TEXTURE_FORMAT_RGBA)
return MESA_FORMAT_ARGB8888;
else
return MESA_FORMAT_XRGB8888;
}
void
nouveau_set_texbuffer(__DRIcontext *dri_ctx,
GLint target, GLint format,
__DRIdrawable *draw)
{
struct nouveau_context *nctx = dri_ctx->driverPrivate;
GLcontext *ctx = &nctx->base;
struct gl_framebuffer *fb = draw->driverPrivate;
struct gl_renderbuffer *rb =
fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
struct gl_texture_object *t = _mesa_get_current_tex_object(ctx, target);
struct gl_texture_image *ti;
struct nouveau_surface *s;
_mesa_lock_texture(ctx, t);
ti = _mesa_get_tex_image(ctx, t, target, 0);
s = &to_nouveau_teximage(ti)->surface;
/* Update the texture surface with the given drawable. */
nouveau_update_renderbuffers(dri_ctx, draw);
nouveau_surface_ref(&to_nouveau_renderbuffer(rb)->surface, s);
/* Update the image fields. */
_mesa_init_teximage_fields(ctx, target, ti, s->width, s->height,
1, 0, s->cpp);
ti->RowStride = s->pitch / s->cpp;
ti->TexFormat = s->format = get_texbuffer_format(rb, format);
/* Try to validate it. */
if (!validate_teximage(ctx, t, 0, 0, 0, 0, s->width, s->height, 1))
nouveau_texture_reallocate(ctx, t);
context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
_mesa_unlock_texture(ctx, t);
}
static void
nouveau_texture_map(GLcontext *ctx, struct gl_texture_object *t)
{
@@ -43,6 +43,11 @@ struct nouveau_texture {
#define texture_dirty(t) \
to_nouveau_texture(t)->dirty = GL_TRUE;
void
nouveau_set_texbuffer(__DRIcontext *dri_ctx,
GLint target, GLint format,
__DRIdrawable *draw);
GLboolean
nouveau_texture_validate(GLcontext *ctx, struct gl_texture_object *t);