X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fstate_tracker%2Fst_atom_framebuffer.c;h=5209a6a0c9c668703dc87ebe52e9612a10efd452;hb=a245c05dd3a1ca48204dd84252e6964aba91d4df;hp=ccbeacfd6e87d4a6b9ba13b49f53315490113c8c;hpb=c9a5ef1a1cdee94fe091cb65ea34e9a9bb8b2190;p=mesa.git diff --git a/src/mesa/state_tracker/st_atom_framebuffer.c b/src/mesa/state_tracker/st_atom_framebuffer.c index ccbeacfd6e8..5209a6a0c9c 100644 --- a/src/mesa/state_tracker/st_atom_framebuffer.c +++ b/src/mesa/state_tracker/st_atom_framebuffer.c @@ -34,62 +34,151 @@ #include "st_context.h" #include "st_atom.h" #include "st_cb_fbo.h" +#include "st_public.h" +#include "st_texture.h" #include "pipe/p_context.h" +#include "pipe/p_inlines.h" +#include "cso_cache/cso_context.h" + + + +/** + * When doing GL render to texture, we have to be sure that finalize_texture() + * didn't yank out the pipe_texture that we earlier created a surface for. + * Check for that here and create a new surface if needed. + */ +static void +update_renderbuffer_surface(struct st_context *st, + struct st_renderbuffer *strb) +{ + struct pipe_screen *screen = st->pipe->screen; + struct pipe_texture *texture = strb->rtt->pt; + int rtt_width = strb->Base.Width; + int rtt_height = strb->Base.Height; + + if (!strb->surface || + strb->surface->texture != texture || + strb->surface->width != rtt_width || + strb->surface->height != rtt_height) { + GLuint level; + /* find matching mipmap level size */ + for (level = 0; level <= texture->last_level; level++) { + if (texture->width[level] == rtt_width && + texture->height[level] == rtt_height) { + + pipe_surface_reference(&strb->surface, NULL); + + strb->surface = screen->get_tex_surface(screen, + texture, + strb->rtt_face, + level, + strb->rtt_slice, + PIPE_BUFFER_USAGE_GPU_READ | + PIPE_BUFFER_USAGE_GPU_WRITE); +#if 0 + printf("-- alloc new surface %d x %d into tex %p\n", + strb->surface->width, strb->surface->height, + texture); +#endif + break; + } + } + } +} /** * Update framebuffer state (color, depth, stencil, etc. buffers) - * XXX someday: separate draw/read buffers. */ static void update_framebuffer_state( struct st_context *st ) { - struct pipe_framebuffer_state framebuffer; + struct pipe_framebuffer_state *framebuffer = &st->state.framebuffer; + struct gl_framebuffer *fb = st->ctx->DrawBuffer; struct st_renderbuffer *strb; GLuint i; - memset(&framebuffer, 0, sizeof(framebuffer)); + framebuffer->width = fb->Width; + framebuffer->height = fb->Height; + + /*printf("------ fb size %d x %d\n", fb->Width, fb->Height);*/ /* Examine Mesa's ctx->DrawBuffer->_ColorDrawBuffers state * to determine which surfaces to draw to */ - framebuffer.num_cbufs = st->ctx->DrawBuffer->_NumColorDrawBuffers[0]; - for (i = 0; i < framebuffer.num_cbufs; i++) { - strb = st_renderbuffer(st->ctx->DrawBuffer->_ColorDrawBuffers[0][i]); - assert(strb->surface); - framebuffer.cbufs[i] = strb->surface; - } + framebuffer->nr_cbufs = 0; + for (i = 0; i < fb->_NumColorDrawBuffers; i++) { + strb = st_renderbuffer(fb->_ColorDrawBuffers[i]); - strb = st_renderbuffer(st->ctx->DrawBuffer->_DepthBuffer); - if (strb) { - strb = st_renderbuffer(strb->Base.Wrapped); - assert(strb->surface); - framebuffer.zbuf = strb->surface; + if (strb) { + /*printf("--------- framebuffer surface rtt %p\n", strb->rtt);*/ + if (strb->rtt) { + /* rendering to a GL texture, may have to update surface */ + update_renderbuffer_surface(st, strb); + } + + if (strb->surface) { + pipe_surface_reference(&framebuffer->cbufs[framebuffer->nr_cbufs], + strb->surface); + framebuffer->nr_cbufs++; + } + strb->defined = GL_TRUE; /* we'll be drawing something */ + } + } + for (i = framebuffer->nr_cbufs; i < PIPE_MAX_COLOR_BUFS; i++) { + pipe_surface_reference(&framebuffer->cbufs[i], NULL); } - strb = st_renderbuffer(st->ctx->DrawBuffer->_StencilBuffer); + /* + * Depth/Stencil renderbuffer/surface. + */ + strb = st_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer); if (strb) { strb = st_renderbuffer(strb->Base.Wrapped); - assert(strb->surface); - framebuffer.sbuf = strb->surface; + if (strb->rtt) { + /* rendering to a GL texture, may have to update surface */ + update_renderbuffer_surface(st, strb); + } + pipe_surface_reference(&framebuffer->zsbuf, strb->surface); + } + else { + strb = st_renderbuffer(fb->Attachment[BUFFER_STENCIL].Renderbuffer); + if (strb) { + strb = st_renderbuffer(strb->Base.Wrapped); + assert(strb->surface); + pipe_surface_reference(&framebuffer->zsbuf, strb->surface); + } + else + pipe_surface_reference(&framebuffer->zsbuf, NULL); } - /* XXX: The memcmp is insufficient for eliminating redundant state changes, - * but we should probably do more work here to that end. - */ - if (1 /*memcmp(&framebuffer, &st->state.framebuffer, sizeof(framebuffer)) != 0*/) { - st->state.framebuffer = framebuffer; - st->pipe->set_framebuffer_state( st->pipe, &framebuffer ); + cso_set_framebuffer(st->cso_context, framebuffer); + + if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) { + if (st->frontbuffer_status == FRONT_STATUS_COPY_OF_BACK) { + /* copy back color buffer to front color buffer */ + struct st_framebuffer *stfb = (struct st_framebuffer *) fb; + struct pipe_surface *surf_front, *surf_back; + (void) st_get_framebuffer_surface(stfb, ST_SURFACE_FRONT_LEFT, &surf_front); + (void) st_get_framebuffer_surface(stfb, ST_SURFACE_BACK_LEFT, &surf_back); + + st->pipe->surface_copy(st->pipe, + surf_front, 0, 0, /* dest */ + surf_back, 0, 0, /* src */ + fb->Width, fb->Height); + } + /* we're assuming we'll really draw to the front buffer */ + st->frontbuffer_status = FRONT_STATUS_DIRTY; } } const struct st_tracked_state st_update_framebuffer = { - .name = "st_update_framebuffer", - .dirty = { - .mesa = _NEW_BUFFERS, - .st = 0, + "st_update_framebuffer", /* name */ + { /* dirty */ + _NEW_BUFFERS, /* mesa */ + ST_NEW_FRAMEBUFFER, /* st */ }, - .update = update_framebuffer_state + update_framebuffer_state /* update */ };