* \file xm_surface.c
* Code to allow the softpipe code to write to X windows/buffers.
* This is a bit of a hack for now. We've basically got two different
- * abstractions for color buffers: gl_renderbuffer and softpipe_surface.
+ * abstractions for color buffers: gl_renderbuffer and pipe_surface.
* They'll need to get merged someday...
* For now, they're separate things that point to each other.
*/
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
-#include "pipe/softpipe/sp_context.h"
-#include "pipe/softpipe/sp_clear.h"
+#include "pipe/p_winsys.h"
+#include "softpipe/sp_context.h"
+#include "softpipe/sp_clear.h"
+#include "softpipe/sp_tile_cache.h"
+#include "softpipe/sp_surface.h"
#include "state_tracker/st_context.h"
+#define CLIP_TILE \
+ do { \
+ if (x + w > ps->width) \
+ w = ps->width - x; \
+ if (y + h > ps->height) \
+ h = ps->height -y; \
+ } while(0)
+
+
static INLINE struct xmesa_surface *
-xmesa_surf(struct softpipe_surface *sps)
+xmesa_surface(struct pipe_surface *ps)
{
- return (struct xmesa_surface *) sps;
+ return (struct xmesa_surface *) ps;
}
static INLINE struct xmesa_renderbuffer *
-xmesa_rb(struct softpipe_surface *sps)
+xmesa_rb(struct pipe_surface *ps)
{
- struct xmesa_surface *xms = xmesa_surf(sps);
+ struct xmesa_surface *xms = xmesa_surface(ps);
return xms->xrb;
}
#define FLIP(Y) Y = xrb->St.Base.Height - (Y) - 1;
-/**
- * quad reading/writing
- * These functions are just wrappers around the existing renderbuffer
- * functions.
- * Note that Y=0 is the top of the surface.
- */
-
-static void
-read_quad_f(struct softpipe_surface *sps, GLint x, GLint y,
- GLfloat (*rgba)[NUM_CHANNELS])
-{
- struct xmesa_renderbuffer *xrb = xmesa_rb(sps);
- GLubyte temp[16];
- GLfloat *dst = (GLfloat *) rgba;
- GLuint i;
- GET_CURRENT_CONTEXT(ctx);
- FLIP(y);
- xrb->St.Base.GetRow(ctx, &xrb->St.Base, 2, x, y, temp);
- xrb->St.Base.GetRow(ctx, &xrb->St.Base, 2, x, y - 1, temp + 8);
- for (i = 0; i < 16; i++) {
- dst[i] = UBYTE_TO_FLOAT(temp[i]);
- }
-}
-
-static void
-read_quad_f_swz(struct softpipe_surface *sps, GLint x, GLint y,
- GLfloat (*rrrr)[QUAD_SIZE])
+void
+xmesa_get_tile_rgba(struct pipe_context *pipe, struct pipe_surface *ps,
+ uint x, uint y, uint w, uint h, float *p)
{
- struct xmesa_renderbuffer *xrb = xmesa_rb(sps);
- GLubyte temp[16];
- GLfloat *dst = (GLfloat *) rrrr;
- GLuint i, j;
- GET_CURRENT_CONTEXT(ctx);
- FLIP(y);
- xrb->St.Base.GetRow(ctx, &xrb->St.Base, 2, x, y, temp);
- xrb->St.Base.GetRow(ctx, &xrb->St.Base, 2, x, y - 1, temp + 8);
- for (i = 0; i < 4; i++) {
- for (j = 0; j < 4; j++) {
- dst[j * 4 + i] = UBYTE_TO_FLOAT(temp[i * 4 + j]);
- }
- }
-}
+ struct xmesa_surface *xms = xmesa_surface(ps);
+ struct xmesa_renderbuffer *xrb = xms->xrb;
+
+ if (xrb) {
+ /* this is a front/back color buffer */
+ GLubyte tmp[MAX_WIDTH * 4];
+ GLuint i, j;
+ uint w0 = w;
+ GET_CURRENT_CONTEXT(ctx);
-static void
-write_quad_f(struct softpipe_surface *sps, GLint x, GLint y,
- GLfloat (*rgba)[NUM_CHANNELS])
-{
- struct xmesa_renderbuffer *xrb = xmesa_rb(sps);
- GLubyte temp[16];
- const GLfloat *src = (const GLfloat *) rgba;
- GLuint i;
- GET_CURRENT_CONTEXT(ctx);
- FLIP(y);
- for (i = 0; i < 16; i++) {
- UNCLAMPED_FLOAT_TO_UBYTE(temp[i], src[i]);
- }
- xrb->St.Base.PutRow(ctx, &xrb->St.Base, 2, x, y, temp, NULL);
- xrb->St.Base.PutRow(ctx, &xrb->St.Base, 2, x, y - 1, temp + 8, NULL);
-}
+ CLIP_TILE;
-static void
-write_quad_f_swz(struct softpipe_surface *sps, GLint x, GLint y,
- GLfloat (*rrrr)[QUAD_SIZE])
-{
- struct xmesa_renderbuffer *xrb = xmesa_rb(sps);
- GLubyte temp[16];
- const GLfloat *src = (const GLfloat *) rrrr;
- GLuint i, j;
- GET_CURRENT_CONTEXT(ctx);
- FLIP(y);
- for (i = 0; i < 4; i++) {
- for (j = 0; j < 4; j++) {
- UNCLAMPED_FLOAT_TO_UBYTE(temp[j * 4 + i], src[i * 4 + j]);
+ FLIP(y);
+ for (i = 0; i < h; i++) {
+ xrb->St.Base.GetRow(ctx, &xrb->St.Base, w, x, y - i, tmp);
+ for (j = 0; j < w * 4; j++) {
+ p[j] = UBYTE_TO_FLOAT(tmp[j]);
+ }
+ p += w0 * 4;
}
}
- xrb->St.Base.PutRow(ctx, &xrb->St.Base, 2, x, y, temp, NULL);
- xrb->St.Base.PutRow(ctx, &xrb->St.Base, 2, x, y - 1, temp + 8, NULL);
-}
-
-static void
-read_quad_ub(struct softpipe_surface *sps, GLint x, GLint y,
- GLubyte (*rgba)[NUM_CHANNELS])
-{
- struct xmesa_renderbuffer *xrb = xmesa_rb(sps);
- GET_CURRENT_CONTEXT(ctx);
- FLIP(y);
- xrb->St.Base.GetRow(ctx, &xrb->St.Base, 2, x, y, rgba);
- xrb->St.Base.GetRow(ctx, &xrb->St.Base, 2, x, y - 1, rgba + 2);
-}
-
-static void
-write_quad_ub(struct softpipe_surface *sps, GLint x, GLint y,
- GLubyte (*rgba)[NUM_CHANNELS])
-{
- struct xmesa_renderbuffer *xrb = xmesa_rb(sps);
- GET_CURRENT_CONTEXT(ctx);
- FLIP(y);
- xrb->St.Base.GetRow(ctx, &xrb->St.Base, 2, x, y, rgba);
- xrb->St.Base.GetRow(ctx, &xrb->St.Base, 2, x, y - 1, rgba + 2);
-}
-
-
-static void
-get_tile(struct pipe_surface *ps,
- GLuint x, GLuint y, GLuint w, GLuint h, GLfloat *p)
-{
- struct xmesa_renderbuffer *xrb = xmesa_rb((struct softpipe_surface *) ps);
- GLubyte tmp[MAX_WIDTH * 4];
- GLuint i, j;
- GET_CURRENT_CONTEXT(ctx);
- FLIP(y);
- for (i = 0; i < h; i++) {
- xrb->St.Base.GetRow(ctx, &xrb->St.Base, w, x, y - i, tmp);
- for (j = 0; j < w * 4; j++) {
- p[j] = UBYTE_TO_FLOAT(tmp[j]);
- }
- p += w * 4;
+ else {
+ /* other softpipe surface */
+ softpipe_get_tile_rgba(ps, x, y, w, h, p);
}
}
-static void
-put_tile(struct pipe_surface *ps,
- GLuint x, GLuint y, GLuint w, GLuint h, const GLfloat *p)
+void
+xmesa_put_tile_rgba(struct pipe_context *pipe, struct pipe_surface *ps,
+ uint x, uint y, uint w, uint h, const float *p)
{
- struct xmesa_renderbuffer *xrb = xmesa_rb((struct softpipe_surface *) ps);
- GLubyte tmp[MAX_WIDTH * 4];
- GLuint i, j;
- GET_CURRENT_CONTEXT(ctx);
- FLIP(y);
- for (i = 0; i < h; i++) {
- for (j = 0; j < w * 4; j++) {
- CLAMPED_FLOAT_TO_UBYTE(tmp[j], p[j]);
+ struct xmesa_surface *xms = xmesa_surface(ps);
+ struct xmesa_renderbuffer *xrb = xms->xrb;
+
+ if (xrb) {
+ /* this is a front/back color buffer */
+ GLubyte tmp[MAX_WIDTH * 4];
+ GLuint i, j;
+ uint w0 = w;
+ GET_CURRENT_CONTEXT(ctx);
+ CLIP_TILE;
+ FLIP(y);
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w * 4; j++) {
+ UNCLAMPED_FLOAT_TO_UBYTE(tmp[j], p[j]);
+ }
+ xrb->St.Base.PutRow(ctx, &xrb->St.Base, w, x, y - i, tmp, NULL);
+ p += w0 * 4;
+ }
+#if 0 /* debug: flush */
+ {
+ XMesaContext xm = XMESA_CONTEXT(ctx);
+ XSync(xm->display, 0);
}
- xrb->St.Base.PutRow(ctx, &xrb->St.Base, w, x, y - i, tmp, NULL);
- p += w * 4;
+#endif
+ }
+ else {
+ /* other softpipe surface */
+ softpipe_put_tile_rgba(ps, x, y, w, h, p);
}
}
assert(pipeFormat);
- xms->surface.surface.format = pipeFormat;
- xms->surface.surface.refcount = 1;
-
- switch (pipeFormat) {
- case PIPE_FORMAT_U_A8_R8_G8_B8:
- xms->surface.read_quad_f_swz = read_quad_f;
- xms->surface.read_quad_f = read_quad_f;
- xms->surface.read_quad_f_swz = read_quad_f_swz;
- xms->surface.read_quad_ub = read_quad_ub;
- xms->surface.write_quad_f = write_quad_f;
- xms->surface.write_quad_f_swz = write_quad_f_swz;
- xms->surface.write_quad_ub = write_quad_ub;
- xms->surface.surface.get_tile = get_tile;
- xms->surface.surface.put_tile = put_tile;
- break;
- case PIPE_FORMAT_S8_Z24:
- softpipe_init_surface_funcs(&xms->surface);
- /*
- xms->surface.read_quad_z = 1;
- xms->surface.write_quad_z = 1;
- */
- break;
- default:
- abort();
- }
+ xms->surface.format = pipeFormat;
+ xms->surface.refcount = 1;
/* Note, the region we allocate doesn't actually have any storage
* since we're drawing into an XImage or Pixmap.
* functions.
*/
if (pipe)
- xms->surface.surface.region = pipe->region_alloc(pipe, 1, 0, 0, 0x0);
+ xms->surface.region = pipe->winsys->region_alloc(pipe->winsys,
+ 1, 0, 0, 0x0);
- return &xms->surface.surface;
+ return &xms->surface;
}
{
struct xmesa_surface *xms = CALLOC_STRUCT(xmesa_surface);
+ assert(pipe);
assert(pipeFormat);
- xms->surface.surface.format = pipeFormat;
- xms->surface.surface.refcount = 1;
- /*
- * This is really just a softpipe surface, not an XImage/Pixmap surface.
- */
- softpipe_init_surface_funcs(&xms->surface);
-
- assert(pipe);
- xms->surface.surface.region = pipe->region_alloc(pipe, 1, 1, 1, 0x0);
+ xms->surface.format = pipeFormat;
+ xms->surface.refcount = 1;
- return &xms->surface.surface;
+ return &xms->surface;
}
-const GLuint *
-xmesa_supported_formats(struct pipe_context *pipe, GLuint *numFormats)
+boolean
+xmesa_is_format_supported(struct pipe_context *pipe, uint format)
{
- static const GLuint formats[] = {
- PIPE_FORMAT_U_A8_R8_G8_B8,
- PIPE_FORMAT_S_R16_G16_B16_A16,
- PIPE_FORMAT_S8_Z24
+ switch( format ) {
+ case PIPE_FORMAT_U_A8_R8_G8_B8:
+ case PIPE_FORMAT_S_R16_G16_B16_A16:
+ case PIPE_FORMAT_S8_Z24:
+ return TRUE;
};
-
- *numFormats = sizeof(formats) / sizeof(formats[0]);
-
- return formats;
+ return FALSE;
}
void
xmesa_clear(struct pipe_context *pipe, struct pipe_surface *ps, GLuint value)
{
- struct xmesa_renderbuffer *xrb = xmesa_rb((struct softpipe_surface *) ps);
+ struct xmesa_renderbuffer *xrb = xmesa_rb(ps);
+
+ /* XXX actually, we should just discard any cached tiles from this
+ * surface since we don't want to accidentally re-use them after clearing.
+ */
+ pipe->flush(pipe, 0);
+
+ {
+ struct softpipe_context *sp = softpipe_context(pipe);
+ if (ps == sp_tile_cache_get_surface(sp->cbuf_cache[0])) {
+ float clear[4];
+ clear[0] = 0.2; /* XXX hack */
+ clear[1] = 0.2;
+ clear[2] = 0.2;
+ clear[3] = 0.2;
+ sp_tile_cache_clear(sp->cbuf_cache[0], clear);
+ }
+ }
if (xrb && xrb->ximage) {
/* clearing back color buffer */