static void intelReadBuffer(struct gl_context * ctx, GLenum mode) { if ((ctx->DrawBuffer != NULL) && (ctx->DrawBuffer->Name == 0)) { struct intel_context *const intel = intel_context(ctx); const GLboolean was_front_buffer_reading = intel->is_front_buffer_reading; intel->is_front_buffer_reading = (mode == GL_FRONT_LEFT) || (mode == GL_FRONT); /* If we weren't front-buffer reading before but we are now, * invalidate our DRI drawable so we'll ask for new buffers * (including the fake front) before we start reading again. */ if (!was_front_buffer_reading && intel->is_front_buffer_reading) dri2InvalidateDrawable(intel->driContext->driReadablePriv); } if (ctx->ReadBuffer == ctx->DrawBuffer) { /* This will update FBO completeness status. * A framebuffer will be incomplete if the GL_READ_BUFFER setting * refers to a missing renderbuffer. Calling glReadBuffer can set * that straight and can make the drawing buffer complete. */ intel_draw_buffer(ctx, ctx->DrawBuffer); } /* Generally, functions which read pixels (glReadPixels, glCopyPixels, etc) * reference ctx->ReadBuffer and do appropriate state checks. */ }
/** * Called via glFramebufferRenderbufferEXT(). */ static void intel_framebuffer_renderbuffer(struct gl_context * ctx, struct gl_framebuffer *fb, GLenum attachment, struct gl_renderbuffer *rb) { DBG("Intel FramebufferRenderbuffer %u %u\n", fb->Name, rb ? rb->Name : 0); _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb); intel_draw_buffer(ctx); }
/** * Called via glBindFramebufferEXT(). */ static void intel_bind_framebuffer(struct gl_context * ctx, GLenum target, struct gl_framebuffer *fb, struct gl_framebuffer *fbread) { if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) { intel_draw_buffer(ctx); } else { /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */ } }
GLboolean intelMakeCurrent(__DRIcontext * driContextPriv, __DRIdrawable * driDrawPriv, __DRIdrawable * driReadPriv) { struct intel_context *intel; GET_CURRENT_CONTEXT(curCtx); if (driContextPriv) intel = (struct intel_context *) driContextPriv->driverPrivate; else intel = NULL; /* According to the glXMakeCurrent() man page: "Pending commands to * the previous context, if any, are flushed before it is released." * But only flush if we're actually changing contexts. */ if (intel_context(curCtx) && intel_context(curCtx) != intel) { _mesa_flush(curCtx); } if (driContextPriv) { struct gl_context *ctx = &intel->ctx; struct gl_framebuffer *fb, *readFb; if (driDrawPriv == NULL && driReadPriv == NULL) { fb = _mesa_get_incomplete_framebuffer(); readFb = _mesa_get_incomplete_framebuffer(); } else { fb = driDrawPriv->driverPrivate; readFb = driReadPriv->driverPrivate; driContextPriv->dri2.draw_stamp = driDrawPriv->dri2.stamp - 1; driContextPriv->dri2.read_stamp = driReadPriv->dri2.stamp - 1; } intel_prepare_render(intel); _mesa_make_current(ctx, fb, readFb); intel_gles3_srgb_workaround(intel, ctx->WinSysDrawBuffer); intel_gles3_srgb_workaround(intel, ctx->WinSysReadBuffer); /* We do this in intel_prepare_render() too, but intel->ctx.DrawBuffer * is NULL at that point. We can't call _mesa_makecurrent() * first, since we need the buffer size for the initial * viewport. So just call intel_draw_buffer() again here. */ intel_draw_buffer(ctx); } else { _mesa_make_current(NULL, NULL, NULL); } return true; }
/** * intel_prepare_render should be called anywhere that curent read/drawbuffer * state is required. */ void intel_prepare_render(struct intel_context *intel) { __DRIcontext *driContext = intel->driContext; __DRIdrawable *drawable; drawable = driContext->driDrawablePriv; if (drawable && drawable->dri2.stamp != driContext->dri2.draw_stamp) { if (drawable->lastStamp != drawable->dri2.stamp) intel_update_renderbuffers(driContext, drawable); intel_draw_buffer(&intel->ctx); driContext->dri2.draw_stamp = drawable->dri2.stamp; } drawable = driContext->driReadablePriv; if (drawable && drawable->dri2.stamp != driContext->dri2.read_stamp) { if (drawable->lastStamp != drawable->dri2.stamp) intel_update_renderbuffers(driContext, drawable); driContext->dri2.read_stamp = drawable->dri2.stamp; } /* If we're currently rendering to the front buffer, the rendering * that will happen next will probably dirty the front buffer. So * mark it as dirty here. */ if (intel->is_front_buffer_rendering) intel->front_buffer_dirty = true; /* Wait for the swapbuffers before the one we just emitted, so we * don't get too many swaps outstanding for apps that are GPU-heavy * but not CPU-heavy. * * We're using intelDRI2Flush (called from the loader before * swapbuffer) and glFlush (for front buffer rendering) as the * indicator that a frame is done and then throttle when we get * here as we prepare to render the next frame. At this point for * round trips for swap/copy and getting new buffers are done and * we'll spend less time waiting on the GPU. * * Unfortunately, we don't have a handle to the batch containing * the swap, and getting our hands on that doesn't seem worth it, * so we just us the first batch we emitted after the last swap. */ if (intel->need_throttle && intel->first_post_swapbuffers_batch) { if (!intel->disable_throttling) drm_intel_bo_wait_rendering(intel->first_post_swapbuffers_batch); drm_intel_bo_unreference(intel->first_post_swapbuffers_batch); intel->first_post_swapbuffers_batch = NULL; intel->need_throttle = false; } }
/** * Called via glBindFramebufferEXT(). */ static void intel_bind_framebuffer(GLcontext * ctx, GLenum target, struct gl_framebuffer *fb, struct gl_framebuffer *fbread) { if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) { intel_draw_buffer(ctx, fb); /* Integer depth range depends on depth buffer bits */ if (ctx->Driver.DepthRange != NULL) ctx->Driver.DepthRange(ctx, ctx->Viewport.Near, ctx->Viewport.Far); } else { /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */ } }
static void intelReadBuffer(GLcontext * ctx, GLenum mode) { if (ctx->ReadBuffer == ctx->DrawBuffer) { /* This will update FBO completeness status. * A framebuffer will be incomplete if the GL_READ_BUFFER setting * refers to a missing renderbuffer. Calling glReadBuffer can set * that straight and can make the drawing buffer complete. */ intel_draw_buffer(ctx, ctx->DrawBuffer); } /* Generally, functions which read pixels (glReadPixels, glCopyPixels, etc) * reference ctx->ReadBuffer and do appropriate state checks. */ }
/** * Called by glFramebufferTexture[123]DEXT() (and other places) to * prepare for rendering into texture memory. This might be called * many times to choose different texture levels, cube faces, etc * before intel_finish_render_texture() is ever called. */ static void intel_render_texture(struct gl_context * ctx, struct gl_framebuffer *fb, struct gl_renderbuffer_attachment *att) { struct intel_context *intel = intel_context(ctx); struct gl_renderbuffer *rb = att->Renderbuffer; struct intel_renderbuffer *irb = intel_renderbuffer(rb); struct gl_texture_image *image = rb->TexImage; struct intel_texture_image *intel_image = intel_texture_image(image); struct intel_mipmap_tree *mt = intel_image->mt; int layer; (void) fb; if (att->CubeMapFace > 0) { assert(att->Zoffset == 0); layer = att->CubeMapFace; } else { layer = att->Zoffset; } if (!intel_image->mt) { /* Fallback on drawing to a texture that doesn't have a miptree * (has a border, width/height 0, etc.) */ _swrast_render_texture(ctx, fb, att); return; } intel_miptree_check_level_layer(mt, att->TextureLevel, layer); if (!intel_renderbuffer_update_wrapper(intel, irb, image, layer)) { _swrast_render_texture(ctx, fb, att); return; } DBG("Begin render %s texture tex=%u w=%d h=%d d=%d refcount=%d\n", _mesa_get_format_name(image->TexFormat), att->Texture->Name, image->Width, image->Height, image->Depth, rb->RefCount); /* update drawing region, etc */ intel_draw_buffer(ctx); }
static void intelDrawBuffer(struct gl_context * ctx, GLenum mode) { if ((ctx->DrawBuffer != NULL) && (ctx->DrawBuffer->Name == 0)) { struct intel_context *const intel = intel_context(ctx); const bool was_front_buffer_rendering = intel->is_front_buffer_rendering; intel->is_front_buffer_rendering = (mode == GL_FRONT_LEFT) || (mode == GL_FRONT) || (mode == GL_FRONT_AND_BACK); /* If we weren't front-buffer rendering before but we are now, * invalidate our DRI drawable so we'll ask for new buffers * (including the fake front) before we start rendering again. */ if (!was_front_buffer_rendering && intel->is_front_buffer_rendering) dri2InvalidateDrawable(intel->driContext->driDrawablePriv); } intel_draw_buffer(ctx); }
void intel_prepare_render(struct intel_context *intel) { __DRIcontext *driContext = intel->driContext; __DRIdrawable *drawable; drawable = intel->driDrawable; if (drawable->dri2.stamp != driContext->dri2.draw_stamp) { if (drawable->lastStamp != drawable->dri2.stamp) intel_update_renderbuffers(driContext, drawable); intel_draw_buffer(&intel->ctx, intel->ctx.DrawBuffer); driContext->dri2.draw_stamp = drawable->dri2.stamp; } drawable = intel->driReadDrawable; if (drawable->dri2.stamp != driContext->dri2.read_stamp) { if (drawable->lastStamp != drawable->dri2.stamp) intel_update_renderbuffers(driContext, drawable); driContext->dri2.read_stamp = drawable->dri2.stamp; } }
static void intelDrawBuffer(GLcontext * ctx, GLenum mode) { if ((ctx->DrawBuffer != NULL) && (ctx->DrawBuffer->Name == 0)) { struct intel_context *const intel = intel_context(ctx); const GLboolean was_front_buffer_rendering = intel->is_front_buffer_rendering; intel->is_front_buffer_rendering = (mode == GL_FRONT_LEFT) || (mode == GL_FRONT); /* If we weren't front-buffer rendering before but we are now, make sure * that the front-buffer has actually been allocated. */ if (!was_front_buffer_rendering && intel->is_front_buffer_rendering) { intel_update_renderbuffers(intel->driContext, intel->driContext->driDrawablePriv); } } intel_draw_buffer(ctx, ctx->DrawBuffer); }
/** * Called by glFramebufferTexture[123]DEXT() (and other places) to * prepare for rendering into texture memory. This might be called * many times to choose different texture levels, cube faces, etc * before intel_finish_render_texture() is ever called. */ static void intel_render_texture(struct gl_context * ctx, struct gl_framebuffer *fb, struct gl_renderbuffer_attachment *att) { struct intel_context *intel = intel_context(ctx); struct gl_texture_image *image = _mesa_get_attachment_teximage(att); struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer); struct intel_texture_image *intel_image = intel_texture_image(image); struct intel_mipmap_tree *mt = intel_image->mt; int layer; (void) fb; if (att->CubeMapFace > 0) { assert(att->Zoffset == 0); layer = att->CubeMapFace; } else { layer = att->Zoffset; } if (!intel_image->mt) { /* Fallback on drawing to a texture that doesn't have a miptree * (has a border, width/height 0, etc.) */ _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); _swrast_render_texture(ctx, fb, att); return; } else if (!irb) { intel_miptree_check_level_layer(mt, att->TextureLevel, layer); irb = (struct intel_renderbuffer *)intel_new_renderbuffer(ctx, ~0); if (irb) { /* bind the wrapper to the attachment point */ _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base.Base); } else { /* fallback to software rendering */ _swrast_render_texture(ctx, fb, att); return; } } if (!intel_renderbuffer_update_wrapper(intel, irb, image, layer)) { _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); _swrast_render_texture(ctx, fb, att); return; } irb->tex_image = image; DBG("Begin render %s texture tex=%u w=%d h=%d refcount=%d\n", _mesa_get_format_name(image->TexFormat), att->Texture->Name, image->Width, image->Height, irb->Base.Base.RefCount); /* update drawing region, etc */ intel_draw_buffer(ctx); }
/** * Called by glFramebufferTexture[123]DEXT() (and other places) to * prepare for rendering into texture memory. This might be called * many times to choose different texture levels, cube faces, etc * before intel_finish_render_texture() is ever called. */ static void intel_render_texture(GLcontext * ctx, struct gl_framebuffer *fb, struct gl_renderbuffer_attachment *att) { struct gl_texture_image *newImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel]; struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer); struct intel_texture_image *intel_image; GLuint dst_x, dst_y; (void) fb; ASSERT(newImage); intel_image = intel_texture_image(newImage); if (!intel_image->mt) { /* Fallback on drawing to a texture that doesn't have a miptree * (has a border, width/height 0, etc.) */ _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); _mesa_render_texture(ctx, fb, att); return; } else if (!irb) { irb = intel_wrap_texture(ctx, newImage); if (irb) { /* bind the wrapper to the attachment point */ _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base); } else { /* fallback to software rendering */ _mesa_render_texture(ctx, fb, att); return; } } if (!intel_update_wrapper(ctx, irb, newImage)) { _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); _mesa_render_texture(ctx, fb, att); return; } DBG("Begin render texture tid %x tex=%u w=%d h=%d refcount=%d\n", _glthread_GetID(), att->Texture->Name, newImage->Width, newImage->Height, irb->Base.RefCount); /* point the renderbufer's region to the texture image region */ if (irb->region != intel_image->mt->region) { if (irb->region) intel_region_release(&irb->region); intel_region_reference(&irb->region, intel_image->mt->region); } /* compute offset of the particular 2D image within the texture region */ intel_miptree_get_image_offset(intel_image->mt, att->TextureLevel, att->CubeMapFace, att->Zoffset, &dst_x, &dst_y); intel_image->mt->region->draw_offset = (dst_y * intel_image->mt->pitch + dst_x) * intel_image->mt->cpp; intel_image->mt->region->draw_x = dst_x; intel_image->mt->region->draw_y = dst_y; intel_image->used_as_render_target = GL_TRUE; /* update drawing region, etc */ intel_draw_buffer(ctx, fb); }
/** * Called by glFramebufferTexture[123]DEXT() (and other places) to * prepare for rendering into texture memory. This might be called * many times to choose different texture levels, cube faces, etc * before intel_finish_render_texture() is ever called. */ static void intel_render_texture(GLcontext * ctx, struct gl_framebuffer *fb, struct gl_renderbuffer_attachment *att) { struct gl_texture_image *newImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel]; struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer); struct intel_texture_image *intel_image; GLuint imageOffset; (void) fb; ASSERT(newImage); if (!irb) { irb = intel_wrap_texture(ctx, newImage); if (irb) { /* bind the wrapper to the attachment point */ _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base); } else { /* fallback to software rendering */ _mesa_render_texture(ctx, fb, att); return; } } if (!intel_update_wrapper(ctx, irb, newImage)) { _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); _mesa_render_texture(ctx, fb, att); return; } DBG("Begin render texture tid %x tex=%u w=%d h=%d refcount=%d\n", _glthread_GetID(), att->Texture->Name, newImage->Width, newImage->Height, irb->Base.RefCount); /* point the renderbufer's region to the texture image region */ intel_image = intel_texture_image(newImage); if (irb->region != intel_image->mt->region) { if (irb->region) intel_region_release(&irb->region); intel_region_reference(&irb->region, intel_image->mt->region); } /* compute offset of the particular 2D image within the texture region */ imageOffset = intel_miptree_image_offset(intel_image->mt, att->CubeMapFace, att->TextureLevel); if (att->Texture->Target == GL_TEXTURE_3D) { const GLuint *offsets = intel_miptree_depth_offsets(intel_image->mt, att->TextureLevel); imageOffset += offsets[att->Zoffset]; } /* store that offset in the region */ intel_image->mt->region->draw_offset = imageOffset; /* update drawing region, etc */ intel_draw_buffer(ctx, fb); }
/** * Called by glFramebufferTexture[123]DEXT() (and other places) to * prepare for rendering into texture memory. This might be called * many times to choose different texture levels, cube faces, etc * before intel_finish_render_texture() is ever called. */ static void intel_render_texture(struct gl_context * ctx, struct gl_framebuffer *fb, struct gl_renderbuffer_attachment *att) { struct intel_context *intel = intel_context(ctx); struct gl_texture_image *image = _mesa_get_attachment_teximage(att); struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer); struct intel_texture_image *intel_image = intel_texture_image(image); struct intel_mipmap_tree *mt = intel_image->mt; int layer; (void) fb; if (att->CubeMapFace > 0) { assert(att->Zoffset == 0); layer = att->CubeMapFace; } else { layer = att->Zoffset; } if (!intel_image->mt) { /* Fallback on drawing to a texture that doesn't have a miptree * (has a border, width/height 0, etc.) */ _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); _swrast_render_texture(ctx, fb, att); return; } else if (!irb) { intel_miptree_check_level_layer(mt, att->TextureLevel, layer); irb = (struct intel_renderbuffer *)intel_new_renderbuffer(ctx, ~0); if (irb) { /* bind the wrapper to the attachment point */ _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base.Base); } else { /* fallback to software rendering */ _swrast_render_texture(ctx, fb, att); return; } } if (!intel_renderbuffer_update_wrapper(intel, irb, image, layer)) { _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); _swrast_render_texture(ctx, fb, att); return; } DBG("Begin render %s texture tex=%u w=%d h=%d refcount=%d\n", _mesa_get_format_name(image->TexFormat), att->Texture->Name, image->Width, image->Height, irb->Base.Base.RefCount); intel_image->used_as_render_target = true; #ifndef I915 if (need_tile_offset_workaround(brw_context(ctx), irb)) { /* Original gen4 hardware couldn't draw to a non-tile-aligned * destination in a miptree unless you actually setup your * renderbuffer as a miptree and used the fragile * lod/array_index/etc. controls to select the image. So, * instead, we just make a new single-level miptree and render * into that. */ struct intel_context *intel = intel_context(ctx); struct intel_mipmap_tree *new_mt; int width, height, depth; intel_miptree_get_dimensions_for_image(image, &width, &height, &depth); new_mt = intel_miptree_create(intel, image->TexObject->Target, intel_image->base.Base.TexFormat, intel_image->base.Base.Level, intel_image->base.Base.Level, width, height, depth, true); intel_miptree_copy_teximage(intel, intel_image, new_mt); intel_renderbuffer_set_draw_offset(irb); intel_miptree_reference(&irb->mt, intel_image->mt); intel_miptree_release(&new_mt); } #endif /* update drawing region, etc */ intel_draw_buffer(ctx); }