Ejemplo n.º 1
0
/**
 * \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_drawing(fb) ||
        brw_is_front_buffer_reading(fb) ||
        !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_batchbuffer_flush(brw);
      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_batchbuffer_flush(brw);
      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);
}
Ejemplo n.º 2
0
static void
intel_glFlush(struct gl_context *ctx)
{
   struct brw_context *brw = brw_context(ctx);

   intel_batchbuffer_flush(brw);
   intel_flush_front(ctx);
   if (brw_is_front_buffer_drawing(ctx->DrawBuffer))
      brw->need_throttle = true;
}
Ejemplo n.º 3
0
static void
intel_update_image_buffers(struct brw_context *brw, __DRIdrawable *drawable)
{
   struct gl_framebuffer *fb = drawable->driverPrivate;
   __DRIscreen *screen = brw->intelScreen->driScrnPriv;
   struct intel_renderbuffer *front_rb;
   struct intel_renderbuffer *back_rb;
   struct __DRIimageList images;
   unsigned int format;
   uint32_t buffer_mask = 0;

   front_rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
   back_rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT);

   if (back_rb)
      format = intel_rb_format(back_rb);
   else if (front_rb)
      format = intel_rb_format(front_rb);
   else
      return;

   if (front_rb && (brw_is_front_buffer_drawing(fb) ||
                    brw_is_front_buffer_reading(fb) || !back_rb)) {
      buffer_mask |= __DRI_IMAGE_BUFFER_FRONT;
   }

   if (back_rb)
      buffer_mask |= __DRI_IMAGE_BUFFER_BACK;

   (*screen->image.loader->getBuffers) (drawable,
                                        driGLFormatToImageFormat(format),
                                        &drawable->dri2.stamp,
                                        drawable->loaderPrivate,
                                        buffer_mask,
                                        &images);

   if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) {
      drawable->w = images.front->width;
      drawable->h = images.front->height;
      intel_update_image_buffer(brw,
                                drawable,
                                front_rb,
                                images.front,
                                __DRI_IMAGE_BUFFER_FRONT);
   }
   if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) {
      drawable->w = images.back->width;
      drawable->h = images.back->height;
      intel_update_image_buffer(brw,
                                drawable,
                                back_rb,
                                images.back,
                                __DRI_IMAGE_BUFFER_BACK);
   }
}
Ejemplo n.º 4
0
static void
intelDrawBuffer(struct gl_context * ctx, GLenum mode)
{
   if (brw_is_front_buffer_drawing(ctx->DrawBuffer)) {
      struct brw_context *const brw = brw_context(ctx);

      /* If we might be front-buffer rendering on this buffer for the first
       * time, invalidate our DRI drawable so we'll ask for new buffers
       * (including the fake front) before we start rendering again.
       */
      dri2InvalidateDrawable(brw->driContext->driDrawablePriv);
   }
}
Ejemplo n.º 5
0
/**
 * intel_prepare_render should be called anywhere that curent read/drawbuffer
 * state is required.
 */
void
intel_prepare_render(struct brw_context *brw)
{
   struct gl_context *ctx = &brw->ctx;
   __DRIcontext *driContext = brw->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);
      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 (brw_is_front_buffer_drawing(ctx->DrawBuffer))
      brw->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 (brw->need_throttle && brw->first_post_swapbuffers_batch) {
      if (!brw->disable_throttling)
         drm_intel_bo_wait_rendering(brw->first_post_swapbuffers_batch);
      drm_intel_bo_unreference(brw->first_post_swapbuffers_batch);
      brw->first_post_swapbuffers_batch = NULL;
      brw->need_throttle = false;
   }
}
Ejemplo n.º 6
0
static void
intel_update_image_buffer(struct brw_context *intel,
                          __DRIdrawable *drawable,
                          struct intel_renderbuffer *rb,
                          __DRIimage *buffer,
                          enum __DRIimageBufferMask buffer_type)
{
   struct intel_region *region = buffer->region;
   struct gl_framebuffer *fb = drawable->driverPrivate;

   if (!rb || !region)
      return;

   unsigned num_samples = rb->Base.Base.NumSamples;

   /* Check and see if we're already bound to the right
    * buffer object
    */
   if (num_samples == 0) {
       if (rb->mt &&
           rb->mt->region &&
           rb->mt->region->bo == region->bo)
          return;
   } else {
       if (rb->singlesample_mt &&
           rb->singlesample_mt->region &&
           rb->singlesample_mt->region->bo == region->bo)
          return;
   }

   intel_update_winsys_renderbuffer_miptree(intel, rb, region);

   if (brw_is_front_buffer_drawing(fb) &&
       buffer_type == __DRI_IMAGE_BUFFER_FRONT &&
       rb->Base.Base.NumSamples > 1) {
      intel_renderbuffer_upsample(intel, rb);
   }
}
Ejemplo n.º 7
0
/**
 * \brief Call this after drawing to mark which buffers need resolving
 *
 * If the depth buffer was written to and if it has an accompanying HiZ
 * buffer, then mark that it needs a depth resolve.
 *
 * If the color buffer is a multisample window system buffer, then
 * mark that it needs a downsample.
 *
 * Also mark any render targets which will be textured as needing a render
 * cache flush.
 */
static void
brw_postdraw_set_buffers_need_resolve(struct brw_context *brw)
{
   struct gl_context *ctx = &brw->ctx;
   struct gl_framebuffer *fb = ctx->DrawBuffer;

   struct intel_renderbuffer *front_irb = NULL;
   struct intel_renderbuffer *back_irb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT);
   struct intel_renderbuffer *depth_irb = intel_get_renderbuffer(fb, BUFFER_DEPTH);
   struct intel_renderbuffer *stencil_irb = intel_get_renderbuffer(fb, BUFFER_STENCIL);
   struct gl_renderbuffer_attachment *depth_att = &fb->Attachment[BUFFER_DEPTH];

   if (brw_is_front_buffer_drawing(fb))
      front_irb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);

   if (front_irb)
      front_irb->need_downsample = true;
   if (back_irb)
      back_irb->need_downsample = true;
   if (depth_irb && ctx->Depth.Mask) {
      intel_renderbuffer_att_set_needs_depth_resolve(depth_att);
      brw_render_cache_set_add_bo(brw, depth_irb->mt->bo);
   }

   if (ctx->Extensions.ARB_stencil_texturing &&
       stencil_irb && ctx->Stencil._WriteEnabled) {
      brw_render_cache_set_add_bo(brw, stencil_irb->mt->bo);
   }

   for (int i = 0; i < fb->_NumColorDrawBuffers; i++) {
      struct intel_renderbuffer *irb =
         intel_renderbuffer(fb->_ColorDrawBuffers[i]);

      if (irb)
         brw_render_cache_set_add_bo(brw, irb->mt->bo);
   }
}
Ejemplo n.º 8
0
static void
intel_update_image_buffer(struct brw_context *intel,
                          __DRIdrawable *drawable,
                          struct intel_renderbuffer *rb,
                          __DRIimage *buffer,
                          enum __DRIimageBufferMask buffer_type)
{
   struct gl_framebuffer *fb = drawable->driverPrivate;

   if (!rb || !buffer->bo)
      return;

   unsigned num_samples = rb->Base.Base.NumSamples;

   /* Check and see if we're already bound to the right
    * buffer object
    */
   struct intel_mipmap_tree *last_mt;
   if (num_samples == 0)
      last_mt = rb->mt;
   else
      last_mt = rb->singlesample_mt;

   if (last_mt && last_mt->bo == buffer->bo)
      return;

   intel_update_winsys_renderbuffer_miptree(intel, rb, buffer->bo,
                                            buffer->width, buffer->height,
                                            buffer->pitch);

   if (brw_is_front_buffer_drawing(fb) &&
       buffer_type == __DRI_IMAGE_BUFFER_FRONT &&
       rb->Base.Base.NumSamples > 1) {
      intel_renderbuffer_upsample(intel, rb);
   }
}
Ejemplo n.º 9
0
/**
 * \brief Assign a DRI buffer's DRM region to a renderbuffer.
 *
 * This is called from intel_update_renderbuffers().
 *
 * \par Note:
 *    DRI buffers whose attachment point is DRI2BufferStencil or
 *    DRI2BufferDepthStencil are handled as special cases.
 *
 * \param buffer_name is a human readable name, such as "dri2 front buffer",
 *        that is passed to drm_intel_bo_gem_create_from_name().
 *
 * \see intel_update_renderbuffers()
 */
static void
intel_process_dri2_buffer(struct brw_context *brw,
                          __DRIdrawable *drawable,
                          __DRIbuffer *buffer,
                          struct intel_renderbuffer *rb,
                          const char *buffer_name)
{
   struct gl_framebuffer *fb = drawable->driverPrivate;
   drm_intel_bo *bo;

   if (!rb)
      return;

   unsigned num_samples = rb->Base.Base.NumSamples;

   /* We try to avoid closing and reopening the same BO name, because the first
    * use of a mapping of the buffer involves a bunch of page faulting which is
    * moderately expensive.
    */
   struct intel_mipmap_tree *last_mt;
   if (num_samples == 0)
      last_mt = rb->mt;
   else
      last_mt = rb->singlesample_mt;

   uint32_t old_name = 0;
   if (last_mt) {
       /* The bo already has a name because the miptree was created by a
	* previous call to intel_process_dri2_buffer(). If a bo already has a
	* name, then drm_intel_bo_flink() is a low-cost getter.  It does not
	* create a new name.
	*/
      drm_intel_bo_flink(last_mt->bo, &old_name);
   }

   if (old_name == buffer->name)
      return;

   if (unlikely(INTEL_DEBUG & DEBUG_DRI)) {
      fprintf(stderr,
              "attaching buffer %d, at %d, cpp %d, pitch %d\n",
              buffer->name, buffer->attachment,
              buffer->cpp, buffer->pitch);
   }

   intel_miptree_release(&rb->mt);
   bo = drm_intel_bo_gem_create_from_name(brw->bufmgr, buffer_name,
                                          buffer->name);
   if (!bo) {
      fprintf(stderr,
              "Failed to open BO for returned DRI2 buffer "
              "(%dx%d, %s, named %d).\n"
              "This is likely a bug in the X Server that will lead to a "
              "crash soon.\n",
              drawable->w, drawable->h, buffer_name, buffer->name);
      return;
   }

   intel_update_winsys_renderbuffer_miptree(brw, rb, bo,
                                            drawable->w, drawable->h,
                                            buffer->pitch);

   if (brw_is_front_buffer_drawing(fb) &&
       (buffer->attachment == __DRI_BUFFER_FRONT_LEFT ||
        buffer->attachment == __DRI_BUFFER_FAKE_FRONT_LEFT) &&
       rb->Base.Base.NumSamples > 1) {
      intel_renderbuffer_upsample(brw, rb);
   }

   assert(rb->mt);

   drm_intel_bo_unreference(bo);
}
Ejemplo n.º 10
0
/**
 * \brief Assign a DRI buffer's DRM region to a renderbuffer.
 *
 * This is called from intel_update_renderbuffers().
 *
 * \par Note:
 *    DRI buffers whose attachment point is DRI2BufferStencil or
 *    DRI2BufferDepthStencil are handled as special cases.
 *
 * \param buffer_name is a human readable name, such as "dri2 front buffer",
 *        that is passed to intel_region_alloc_for_handle().
 *
 * \see intel_update_renderbuffers()
 * \see intel_region_alloc_for_handle()
 */
static void
intel_process_dri2_buffer(struct brw_context *brw,
                          __DRIdrawable *drawable,
                          __DRIbuffer *buffer,
                          struct intel_renderbuffer *rb,
                          const char *buffer_name)
{
   struct intel_region *region = NULL;
   struct gl_framebuffer *fb = drawable->driverPrivate;

   if (!rb)
      return;

   unsigned num_samples = rb->Base.Base.NumSamples;

   /* We try to avoid closing and reopening the same BO name, because the first
    * use of a mapping of the buffer involves a bunch of page faulting which is
    * moderately expensive.
    */
   if (num_samples == 0) {
       if (rb->mt &&
           rb->mt->region &&
           rb->mt->region->name == buffer->name)
          return;
   } else {
       if (rb->singlesample_mt &&
           rb->singlesample_mt->region &&
           rb->singlesample_mt->region->name == buffer->name)
          return;
   }

   if (unlikely(INTEL_DEBUG & DEBUG_DRI)) {
      fprintf(stderr,
              "attaching buffer %d, at %d, cpp %d, pitch %d\n",
              buffer->name, buffer->attachment,
              buffer->cpp, buffer->pitch);
   }

   intel_miptree_release(&rb->mt);
   region = intel_region_alloc_for_handle(brw->intelScreen,
                                          buffer->cpp,
                                          drawable->w,
                                          drawable->h,
                                          buffer->pitch,
                                          buffer->name,
                                          buffer_name);
   if (!region) {
      fprintf(stderr,
              "Failed to make region for returned DRI2 buffer "
              "(%dx%d, named %d).\n"
              "This is likely a bug in the X Server that will lead to a "
              "crash soon.\n",
              drawable->w, drawable->h, buffer->name);
      return;
   }

   intel_update_winsys_renderbuffer_miptree(brw, rb, region);

   if (brw_is_front_buffer_drawing(fb) &&
       (buffer->attachment == __DRI_BUFFER_FRONT_LEFT ||
        buffer->attachment == __DRI_BUFFER_FAKE_FRONT_LEFT) &&
       rb->Base.Base.NumSamples > 1) {
      intel_renderbuffer_upsample(brw, rb);
   }

   assert(rb->mt);

   intel_region_release(&region);
}