/** * \brief Query DRI2 to obtain a DRIdrawable's buffers. * * To determine which DRI buffers to request, examine the renderbuffers * attached to the drawable's framebuffer. Then request the buffers with * DRI2GetBuffers() or DRI2GetBuffersWithFormat(). * * This is called from intel_update_renderbuffers(). * * \param drawable Drawable whose buffers are queried. * \param buffers [out] List of buffers returned by DRI2 query. * \param buffer_count [out] Number of buffers returned. * * \see intel_update_renderbuffers() * \see DRI2GetBuffers() * \see DRI2GetBuffersWithFormat() */ static void intel_query_dri2_buffers(struct brw_context *brw, __DRIdrawable *drawable, __DRIbuffer **buffers, int *buffer_count) { __DRIscreen *screen = brw->intelScreen->driScrnPriv; struct gl_framebuffer *fb = drawable->driverPrivate; int i = 0; unsigned attachments[8]; struct intel_renderbuffer *front_rb; struct intel_renderbuffer *back_rb; front_rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); back_rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT); memset(attachments, 0, sizeof(attachments)); if ((brw->is_front_buffer_rendering || brw->is_front_buffer_reading || !back_rb) && front_rb) { /* If a fake front buffer is in use, then querying for * __DRI_BUFFER_FRONT_LEFT will cause the server to copy the image from * the real front buffer to the fake front buffer. So before doing the * query, we need to make sure all the pending drawing has landed in the * real front buffer. */ intel_flush(&brw->ctx); intel_flush_front(&brw->ctx); attachments[i++] = __DRI_BUFFER_FRONT_LEFT; attachments[i++] = intel_bits_per_pixel(front_rb); } else if (front_rb && brw->front_buffer_dirty) { /* We have pending front buffer rendering, but we aren't querying for a * front buffer. If the front buffer we have is a fake front buffer, * the X server is going to throw it away when it processes the query. * So before doing the query, make sure all the pending drawing has * landed in the real front buffer. */ intel_flush(&brw->ctx); intel_flush_front(&brw->ctx); } if (back_rb) { attachments[i++] = __DRI_BUFFER_BACK_LEFT; attachments[i++] = intel_bits_per_pixel(back_rb); } assert(i <= ARRAY_SIZE(attachments)); *buffers = screen->dri2.loader->getBuffersWithFormat(drawable, &drawable->w, &drawable->h, attachments, i / 2, buffer_count, drawable->loaderPrivate); }
/** * \brief Query DRI2 to obtain a DRIdrawable's buffers. * * To determine which DRI buffers to request, examine the renderbuffers * attached to the drawable's framebuffer. Then request the buffers with * DRI2GetBuffers() or DRI2GetBuffersWithFormat(). * * This is called from intel_update_renderbuffers(). * * \param drawable Drawable whose buffers are queried. * \param buffers [out] List of buffers returned by DRI2 query. * \param buffer_count [out] Number of buffers returned. * * \see intel_update_renderbuffers() * \see DRI2GetBuffers() * \see DRI2GetBuffersWithFormat() */ static void intel_query_dri2_buffers(struct intel_context *intel, __DRIdrawable *drawable, __DRIbuffer **buffers, int *buffer_count) { __DRIscreen *screen = intel->intelScreen->driScrnPriv; struct gl_framebuffer *fb = drawable->driverPrivate; int i = 0; const int max_attachments = 4; unsigned *attachments = calloc(2 * max_attachments, sizeof(unsigned)); struct intel_renderbuffer *front_rb; struct intel_renderbuffer *back_rb; front_rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); back_rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT); if ((intel->is_front_buffer_rendering || intel->is_front_buffer_reading || !back_rb) && front_rb) { attachments[i++] = __DRI_BUFFER_FRONT_LEFT; attachments[i++] = intel_bits_per_pixel(front_rb); } if (back_rb) { attachments[i++] = __DRI_BUFFER_BACK_LEFT; attachments[i++] = intel_bits_per_pixel(back_rb); } assert(i <= 2 * max_attachments); *buffers = screen->dri2.loader->getBuffersWithFormat(drawable, &drawable->w, &drawable->h, attachments, i / 2, buffer_count, drawable->loaderPrivate); free(attachments); }
void intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable) { struct gl_framebuffer *fb = drawable->driverPrivate; struct intel_renderbuffer *rb; struct intel_region *region, *depth_region; struct intel_context *intel = context->driverPrivate; struct intel_renderbuffer *front_rb, *back_rb, *depth_rb, *stencil_rb; __DRIbuffer *buffers = NULL; __DRIscreen *screen; int i, count; unsigned int attachments[10]; const char *region_name; /* If we're rendering to the fake front buffer, make sure all the * pending drawing has landed on the real front buffer. Otherwise * when we eventually get to DRI2GetBuffersWithFormat the stale * real front buffer contents will get copied to the new fake front * buffer. */ if (intel->is_front_buffer_rendering) intel_flush(&intel->ctx, GL_FALSE); /* Set this up front, so that in case our buffers get invalidated * while we're getting new buffers, we don't clobber the stamp and * thus ignore the invalidate. */ drawable->lastStamp = drawable->dri2.stamp; if (INTEL_DEBUG & DEBUG_DRI) fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable); screen = intel->intelScreen->driScrnPriv; if (screen->dri2.loader && (screen->dri2.loader->base.version > 2) && (screen->dri2.loader->getBuffersWithFormat != NULL)) { front_rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); back_rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT); depth_rb = intel_get_renderbuffer(fb, BUFFER_DEPTH); stencil_rb = intel_get_renderbuffer(fb, BUFFER_STENCIL); i = 0; if ((intel->is_front_buffer_rendering || intel->is_front_buffer_reading || !back_rb) && front_rb) { attachments[i++] = __DRI_BUFFER_FRONT_LEFT; attachments[i++] = intel_bits_per_pixel(front_rb); } if (back_rb) { attachments[i++] = __DRI_BUFFER_BACK_LEFT; attachments[i++] = intel_bits_per_pixel(back_rb); } if ((depth_rb != NULL) && (stencil_rb != NULL)) { attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL; attachments[i++] = intel_bits_per_pixel(depth_rb); } else if (depth_rb != NULL) { attachments[i++] = __DRI_BUFFER_DEPTH; attachments[i++] = intel_bits_per_pixel(depth_rb); } else if (stencil_rb != NULL) { attachments[i++] = __DRI_BUFFER_STENCIL; attachments[i++] = intel_bits_per_pixel(stencil_rb); } buffers = (*screen->dri2.loader->getBuffersWithFormat)(drawable, &drawable->w, &drawable->h, attachments, i / 2, &count, drawable->loaderPrivate); } else if (screen->dri2.loader) { i = 0; if (intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT)) attachments[i++] = __DRI_BUFFER_FRONT_LEFT; if (intel_get_renderbuffer(fb, BUFFER_BACK_LEFT)) attachments[i++] = __DRI_BUFFER_BACK_LEFT; if (intel_get_renderbuffer(fb, BUFFER_DEPTH)) attachments[i++] = __DRI_BUFFER_DEPTH; if (intel_get_renderbuffer(fb, BUFFER_STENCIL)) attachments[i++] = __DRI_BUFFER_STENCIL; buffers = (*screen->dri2.loader->getBuffers)(drawable, &drawable->w, &drawable->h, attachments, i, &count, drawable->loaderPrivate); } if (buffers == NULL) return; drawable->x = 0; drawable->y = 0; drawable->backX = 0; drawable->backY = 0; drawable->numClipRects = 1; drawable->pClipRects[0].x1 = 0; drawable->pClipRects[0].y1 = 0; drawable->pClipRects[0].x2 = drawable->w; drawable->pClipRects[0].y2 = drawable->h; drawable->numBackClipRects = 1; drawable->pBackClipRects[0].x1 = 0; drawable->pBackClipRects[0].y1 = 0; drawable->pBackClipRects[0].x2 = drawable->w; drawable->pBackClipRects[0].y2 = drawable->h; depth_region = NULL; for (i = 0; i < count; i++) { switch (buffers[i].attachment) { case __DRI_BUFFER_FRONT_LEFT: rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); region_name = "dri2 front buffer"; break; case __DRI_BUFFER_FAKE_FRONT_LEFT: rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); region_name = "dri2 fake front buffer"; break; case __DRI_BUFFER_BACK_LEFT: rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT); region_name = "dri2 back buffer"; break; case __DRI_BUFFER_DEPTH: rb = intel_get_renderbuffer(fb, BUFFER_DEPTH); region_name = "dri2 depth buffer"; break; case __DRI_BUFFER_DEPTH_STENCIL: rb = intel_get_renderbuffer(fb, BUFFER_DEPTH); region_name = "dri2 depth / stencil buffer"; break; case __DRI_BUFFER_STENCIL: rb = intel_get_renderbuffer(fb, BUFFER_STENCIL); region_name = "dri2 stencil buffer"; break; case __DRI_BUFFER_ACCUM: default: fprintf(stderr, "unhandled buffer attach event, attacment type %d\n", buffers[i].attachment); return; } if (rb == NULL) continue; if (rb->region && rb->region->name == buffers[i].name) continue; if (INTEL_DEBUG & DEBUG_DRI) fprintf(stderr, "attaching buffer %d, at %d, cpp %d, pitch %d\n", buffers[i].name, buffers[i].attachment, buffers[i].cpp, buffers[i].pitch); if (buffers[i].attachment == __DRI_BUFFER_STENCIL && depth_region) { if (INTEL_DEBUG & DEBUG_DRI) fprintf(stderr, "(reusing depth buffer as stencil)\n"); intel_region_reference(®ion, depth_region); } else region = intel_region_alloc_for_handle(intel, buffers[i].cpp, drawable->w, drawable->h, buffers[i].pitch / buffers[i].cpp, buffers[i].name, region_name); if (buffers[i].attachment == __DRI_BUFFER_DEPTH) depth_region = region; intel_renderbuffer_set_region(intel, rb, region); intel_region_release(®ion); if (buffers[i].attachment == __DRI_BUFFER_DEPTH_STENCIL) { rb = intel_get_renderbuffer(fb, BUFFER_STENCIL); if (rb != NULL) { struct intel_region *stencil_region = NULL; if (rb->region && rb->region->name == buffers[i].name) continue; intel_region_reference(&stencil_region, region); intel_renderbuffer_set_region(intel, rb, stencil_region); intel_region_release(&stencil_region); } } } driUpdateFramebufferSize(&intel->ctx, drawable); }