static GLboolean dri_make_current(__DRIcontext * cPriv, __DRIdrawable * driDrawPriv, __DRIdrawable * driReadPriv) { struct gl_context *mesaCtx; struct gl_framebuffer *mesaDraw; struct gl_framebuffer *mesaRead; TRACE; if (cPriv) { struct dri_context *ctx = dri_context(cPriv); struct dri_drawable *draw; struct dri_drawable *read; if (!driDrawPriv || !driReadPriv) return GL_FALSE; draw = dri_drawable(driDrawPriv); read = dri_drawable(driReadPriv); mesaCtx = &ctx->Base; mesaDraw = &draw->Base; mesaRead = &read->Base; /* check for same context and buffer */ if (mesaCtx == _mesa_get_current_context() && mesaCtx->DrawBuffer == mesaDraw && mesaCtx->ReadBuffer == mesaRead) { return GL_TRUE; } _glapi_check_multithread(); swrast_check_and_update_window_size(mesaCtx, mesaDraw); if (mesaRead != mesaDraw) swrast_check_and_update_window_size(mesaCtx, mesaRead); _mesa_make_current( mesaCtx, mesaDraw, mesaRead ); } else { /* unbind */ _mesa_make_current( NULL, NULL, NULL ); } return GL_TRUE; }
static void dri_copy_sub_buffer(__DRIdrawable *dPriv, int x, int y, int w, int h) { __DRIscreen *sPriv = dPriv->driScreenPriv; void *data; int iy; struct dri_drawable *drawable = dri_drawable(dPriv); struct gl_framebuffer *fb; struct dri_swrast_renderbuffer *frontrb, *backrb; TRACE; fb = &drawable->Base; frontrb = dri_swrast_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer); backrb = dri_swrast_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer); /* check for signle-buffered */ if (backrb == NULL) return; iy = frontrb->Base.Base.Height - y - h; data = (char *)backrb->Base.Buffer + (iy * backrb->pitch) + (x * ((backrb->bpp + 7) / 8)); sPriv->swrast_loader->putImage2(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP, x, iy, w, h, frontrb->pitch, data, dPriv->loaderPrivate); }
static inline void drisw_invalidate_drawable(__DRIdrawable *dPriv) { struct dri_drawable *drawable = dri_drawable(dPriv); drawable->texture_stamp = dPriv->lastStamp - 1; p_atomic_inc(&drawable->base.stamp); }
static void dri2_invalidate_drawable(__DRIdrawable *dPriv) { struct dri_drawable *drawable = dri_drawable(dPriv); dri2InvalidateDrawable(dPriv); drawable->dPriv->lastStamp = drawable->dPriv->dri2.stamp; p_atomic_inc(&drawable->base.stamp); }
GLboolean dri_make_current(__DRIcontext * cPriv, __DRIdrawable * driDrawPriv, __DRIdrawable * driReadPriv) { /* dri_util.c ensures cPriv is not null */ struct dri_context *ctx = dri_context(cPriv); struct dri_drawable *draw = dri_drawable(driDrawPriv); struct dri_drawable *read = dri_drawable(driReadPriv); struct st_context_iface *old_st = ctx->stapi->get_current(ctx->stapi); /* Flush the old context here so we don't have to flush on unbind() */ if (old_st && old_st != ctx->st) old_st->flush(old_st, ST_FLUSH_FRONT, NULL); ++ctx->bind_count; if (!driDrawPriv && !driReadPriv) return ctx->stapi->make_current(ctx->stapi, ctx->st, NULL, NULL); else if (!driDrawPriv || !driReadPriv) return GL_FALSE; if (ctx->dPriv != driDrawPriv) { ctx->dPriv = driDrawPriv; draw->texture_stamp = driDrawPriv->lastStamp - 1; } if (ctx->rPriv != driReadPriv) { ctx->rPriv = driReadPriv; read->texture_stamp = driReadPriv->lastStamp - 1; } ctx->stapi->make_current(ctx->stapi, ctx->st, &draw->base, &read->base); // This is ok to call here. If they are already init, it's a no-op. if (draw->textures[ST_ATTACHMENT_BACK_LEFT] && draw->textures[ST_ATTACHMENT_DEPTH_STENCIL] && ctx->pp) pp_init_fbos(ctx->pp, draw->textures[ST_ATTACHMENT_BACK_LEFT]->width0, draw->textures[ST_ATTACHMENT_BACK_LEFT]->height0); return GL_TRUE; }
static void dri2_invalidate_drawable(__DRIdrawable *dPriv) { struct dri_drawable *drawable = dri_drawable(dPriv); struct dri_context *ctx = drawable->context; dri2InvalidateDrawable(dPriv); drawable->dPriv->lastStamp = *drawable->dPriv->pStamp; if (ctx) ctx->st->notify_invalid_framebuffer(ctx->st, &drawable->base); }
static inline void drisw_present_texture(__DRIdrawable *dPriv, struct pipe_resource *ptex, struct pipe_box *sub_box) { struct dri_drawable *drawable = dri_drawable(dPriv); struct dri_screen *screen = dri_screen(drawable->sPriv); if (swrast_no_present) return; screen->base.screen->flush_frontbuffer(screen->base.screen, ptex, 0, 0, drawable, sub_box); }
/** * DRI2 flush extension. */ static void dri2_flush_drawable(__DRIdrawable *dPriv) { struct dri_context *ctx = dri_get_current(dPriv->driScreenPriv); struct dri_drawable *drawable = dri_drawable(dPriv); struct pipe_resource *ptex = drawable->textures[ST_ATTACHMENT_BACK_LEFT]; if (ctx) { if (ptex && ctx->pp && drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]) pp_run(ctx->pp, ptex, ptex, drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]); ctx->st->flush(ctx->st, 0, NULL); } }
static void dri_destroy_buffer(__DRIdrawable * dPriv) { TRACE; if (dPriv) { struct dri_drawable *drawable = dri_drawable(dPriv); struct gl_framebuffer *fb; free(drawable->row); fb = &drawable->Base; fb->DeletePending = GL_TRUE; _mesa_reference_framebuffer(&fb, NULL); } }
void dri_destroy_buffer(__DRIdrawable * dPriv) { struct dri_drawable *drawable = dri_drawable(dPriv); int i; pipe_surface_reference(&drawable->drisw_surface, NULL); for (i = 0; i < ST_ATTACHMENT_COUNT; i++) pipe_resource_reference(&drawable->textures[i], NULL); for (i = 0; i < ST_ATTACHMENT_COUNT; i++) pipe_resource_reference(&drawable->msaa_textures[i], NULL); swap_fences_unref(drawable); FREE(drawable); }
/** * These are used for GLX_EXT_texture_from_pixmap */ static void dri_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target, GLint format, __DRIdrawable *dPriv) { struct dri_context *ctx = dri_context(pDRICtx); struct st_context_iface *st = ctx->st; struct dri_drawable *drawable = dri_drawable(dPriv); struct pipe_resource *pt; if (st->thread_finish) st->thread_finish(st); dri_drawable_validate_att(ctx, drawable, ST_ATTACHMENT_FRONT_LEFT); /* Use the pipe resource associated with the X drawable */ pt = drawable->textures[ST_ATTACHMENT_FRONT_LEFT]; if (pt) { enum pipe_format internal_format = pt->format; if (format == __DRI_TEXTURE_FORMAT_RGB) { /* only need to cover the formats recognized by dri_fill_st_visual */ switch (internal_format) { case PIPE_FORMAT_BGRA8888_UNORM: internal_format = PIPE_FORMAT_BGRX8888_UNORM; break; case PIPE_FORMAT_ARGB8888_UNORM: internal_format = PIPE_FORMAT_XRGB8888_UNORM; break; default: break; } } drawable->update_tex_buffer(drawable, ctx, pt); ctx->st->teximage(ctx->st, (target == GL_TEXTURE_2D) ? ST_TEXTURE_2D : ST_TEXTURE_RECT, 0, internal_format, pt, FALSE); } }
static void drisw_swap_buffers(__DRIdrawable *dPriv) { struct dri_context *ctx = dri_get_current(dPriv->driScreenPriv); struct dri_drawable *drawable = dri_drawable(dPriv); struct pipe_resource *ptex; if (!ctx) return; ptex = drawable->textures[ST_ATTACHMENT_BACK_LEFT]; if (ptex) { if (ctx->pp) pp_run(ctx->pp, ptex, ptex, drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]); ctx->st->flush(ctx->st, ST_FLUSH_FRONT, NULL); drisw_copy_to_front(dPriv, ptex); } }
void dri_destroy_buffer(__DRIdrawable * dPriv) { struct dri_drawable *drawable = dri_drawable(dPriv); struct dri_screen *screen = drawable->screen; struct st_api *stapi = screen->st_api; int i; pipe_surface_reference(&drawable->drisw_surface, NULL); for (i = 0; i < ST_ATTACHMENT_COUNT; i++) pipe_resource_reference(&drawable->textures[i], NULL); for (i = 0; i < ST_ATTACHMENT_COUNT; i++) pipe_resource_reference(&drawable->msaa_textures[i], NULL); swap_fences_unref(drawable); /* Notify the st manager that this drawable is no longer valid */ stapi->destroy_drawable(stapi, &drawable->base); FREE(drawable); }
static void drisw_copy_sub_buffer(__DRIdrawable *dPriv, int x, int y, int w, int h) { struct dri_context *ctx = dri_get_current(dPriv->driScreenPriv); struct dri_drawable *drawable = dri_drawable(dPriv); struct pipe_resource *ptex; struct pipe_box box; if (!ctx) return; ptex = drawable->textures[ST_ATTACHMENT_BACK_LEFT]; if (ptex) { if (ctx->pp && drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]) pp_run(ctx->pp, ptex, ptex, drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]); ctx->st->flush(ctx->st, ST_FLUSH_FRONT, NULL); u_box_2d(x, dPriv->h - y - h, w, h, &box); drisw_present_texture(dPriv, ptex, &box); } }
static void dri_swap_buffers(__DRIdrawable * dPriv) { __DRIscreen *sPriv = dPriv->driScreenPriv; GET_CURRENT_CONTEXT(ctx); struct dri_drawable *drawable = dri_drawable(dPriv); struct gl_framebuffer *fb; struct swrast_renderbuffer *frontrb, *backrb; TRACE; fb = &drawable->Base; frontrb = swrast_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer); backrb = swrast_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer); /* check for signle-buffered */ if (backrb == NULL) return; /* check if swapping currently bound buffer */ if (ctx && ctx->DrawBuffer == fb) { /* flush pending rendering */ _mesa_notifySwapBuffers(ctx); } sPriv->swrast_loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP, 0, 0, frontrb->Base.Width, frontrb->Base.Height, backrb->Base.Data, dPriv->loaderPrivate); }
/** * DRI2 flush extension, the flush_with_flags function. * * \param context the context * \param drawable the drawable to flush * \param flags a combination of _DRI2_FLUSH_xxx flags * \param throttle_reason the reason for throttling, 0 = no throttling */ void dri_flush(__DRIcontext *cPriv, __DRIdrawable *dPriv, unsigned flags, enum __DRI2throttleReason reason) { struct dri_context *ctx = dri_context(cPriv); struct dri_drawable *drawable = dri_drawable(dPriv); unsigned flush_flags; boolean swap_msaa_buffers = FALSE; if (!ctx) { assert(0); return; } if (drawable) { /* prevent recursion */ if (drawable->flushing) return; drawable->flushing = TRUE; } else { flags &= ~__DRI2_FLUSH_DRAWABLE; } /* Flush the drawable. */ if ((flags & __DRI2_FLUSH_DRAWABLE) && drawable->textures[ST_ATTACHMENT_BACK_LEFT]) { struct pipe_context *pipe = ctx->st->pipe; if (drawable->stvis.samples > 1 && reason == __DRI2_THROTTLE_SWAPBUFFER) { /* Resolve the MSAA back buffer. */ dri_pipe_blit(ctx->st->pipe, drawable->textures[ST_ATTACHMENT_BACK_LEFT], drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]); if (drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT] && drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]) { swap_msaa_buffers = TRUE; } /* FRONT_LEFT is resolved in drawable->flush_frontbuffer. */ } dri_postprocessing(ctx, drawable, ST_ATTACHMENT_BACK_LEFT); if (ctx->hud) { hud_draw(ctx->hud, drawable->textures[ST_ATTACHMENT_BACK_LEFT]); } pipe->flush_resource(pipe, drawable->textures[ST_ATTACHMENT_BACK_LEFT]); } flush_flags = 0; if (flags & __DRI2_FLUSH_CONTEXT) flush_flags |= ST_FLUSH_FRONT; if (reason == __DRI2_THROTTLE_SWAPBUFFER) flush_flags |= ST_FLUSH_END_OF_FRAME; /* Flush the context and throttle if needed. */ if (dri_screen(ctx->sPriv)->throttling_enabled && drawable && (reason == __DRI2_THROTTLE_SWAPBUFFER || reason == __DRI2_THROTTLE_FLUSHFRONT)) { /* Throttle. * * This pulls a fence off the throttling queue and waits for it if the * number of fences on the throttling queue has reached the desired * number. * * Then flushes to insert a fence at the current rendering position, and * pushes that fence on the queue. This requires that the st_context_iface * flush method returns a fence even if there are no commands to flush. */ struct pipe_screen *screen = drawable->screen->base.screen; struct pipe_fence_handle *fence; fence = swap_fences_pop_front(drawable); if (fence) { (void) screen->fence_finish(screen, fence, PIPE_TIMEOUT_INFINITE); screen->fence_reference(screen, &fence, NULL); } ctx->st->flush(ctx->st, flush_flags, &fence); if (fence) { swap_fences_push_back(drawable, fence); screen->fence_reference(screen, &fence, NULL); } } else if (flags & (__DRI2_FLUSH_DRAWABLE | __DRI2_FLUSH_CONTEXT)) { ctx->st->flush(ctx->st, flush_flags, NULL); } if (drawable) { drawable->flushing = FALSE; } /* Swap the MSAA front and back buffers, so that reading * from the front buffer after SwapBuffers returns what was * in the back buffer. */ if (swap_msaa_buffers) { struct pipe_resource *tmp = drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT]; drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT] = drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]; drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT] = tmp; /* Now that we have swapped the buffers, this tells the state * tracker to revalidate the framebuffer. */ p_atomic_inc(&drawable->base.stamp); } }