/** dri3_free_buffers * * Free the front bufffer or all of the back buffers. Used * when the application changes which buffers it needs */ static void dri3_free_buffers(__DRIdrawable *driDrawable, enum loader_dri3_buffer_type buffer_type, struct loader_dri3_drawable *draw) { struct loader_dri3_buffer *buffer; int first_id; int n_id; int buf_id; switch (buffer_type) { case loader_dri3_buffer_back: first_id = LOADER_DRI3_BACK_ID(0); n_id = LOADER_DRI3_MAX_BACK; break; case loader_dri3_buffer_front: first_id = LOADER_DRI3_FRONT_ID; n_id = 1; } for (buf_id = first_id; buf_id < first_id + n_id; buf_id++) { buffer = draw->buffers[buf_id]; if (buffer) { dri3_free_render_buffer(draw, buffer); draw->buffers[buf_id] = NULL; } } }
void loader_dri3_drawable_fini(struct loader_dri3_drawable *draw) { int i; (draw->ext->core->destroyDrawable)(draw->dri_drawable); for (i = 0; i < LOADER_DRI3_NUM_BUFFERS; i++) { if (draw->buffers[i]) dri3_free_render_buffer(draw, draw->buffers[i]); } if (draw->special_event) xcb_unregister_for_special_event(draw->conn, draw->special_event); }
void loader_dri3_drawable_fini(struct loader_dri3_drawable *draw) { int i; (draw->ext->core->destroyDrawable)(draw->dri_drawable); for (i = 0; i < LOADER_DRI3_NUM_BUFFERS; i++) { if (draw->buffers[i]) dri3_free_render_buffer(draw, draw->buffers[i]); } if (draw->special_event) { xcb_void_cookie_t cookie = xcb_present_select_input_checked(draw->conn, draw->eid, draw->drawable, XCB_PRESENT_EVENT_MASK_NO_EVENT); xcb_discard_reply(draw->conn, cookie.sequence); xcb_unregister_for_special_event(draw->conn, draw->special_event); } }
/* * Process one Present event */ static void dri3_handle_present_event(struct loader_dri3_drawable *draw, xcb_present_generic_event_t *ge) { switch (ge->evtype) { case XCB_PRESENT_CONFIGURE_NOTIFY: { xcb_present_configure_notify_event_t *ce = (void *) ge; draw->width = ce->width; draw->height = ce->height; draw->vtable->set_drawable_size(draw, draw->width, draw->height); break; } case XCB_PRESENT_COMPLETE_NOTIFY: { xcb_present_complete_notify_event_t *ce = (void *) ge; /* Compute the processed SBC number from the received 32-bit serial number * merged with the upper 32-bits of the sent 64-bit serial number while * checking for wrap. */ if (ce->kind == XCB_PRESENT_COMPLETE_KIND_PIXMAP) { draw->recv_sbc = (draw->send_sbc & 0xffffffff00000000LL) | ce->serial; if (draw->recv_sbc > draw->send_sbc) draw->recv_sbc -= 0x100000000; switch (ce->mode) { case XCB_PRESENT_COMPLETE_MODE_FLIP: draw->flipping = true; break; case XCB_PRESENT_COMPLETE_MODE_COPY: draw->flipping = false; break; } dri3_update_num_back(draw); if (draw->vtable->show_fps) draw->vtable->show_fps(draw, ce->ust); draw->ust = ce->ust; draw->msc = ce->msc; } else { draw->recv_msc_serial = ce->serial; draw->notify_ust = ce->ust; draw->notify_msc = ce->msc; } break; } case XCB_PRESENT_EVENT_IDLE_NOTIFY: { xcb_present_idle_notify_event_t *ie = (void *) ge; int b; for (b = 0; b < sizeof(draw->buffers) / sizeof(draw->buffers[0]); b++) { struct loader_dri3_buffer *buf = draw->buffers[b]; if (buf && buf->pixmap == ie->pixmap) { buf->busy = 0; if (draw->num_back <= b && b < LOADER_DRI3_MAX_BACK) { dri3_free_render_buffer(draw, buf); draw->buffers[b] = NULL; } break; } } break; } } free(ge); }
/** dri3_get_buffer * * Find a front or back buffer, allocating new ones as necessary */ static struct loader_dri3_buffer * dri3_get_buffer(__DRIdrawable *driDrawable, unsigned int format, enum loader_dri3_buffer_type buffer_type, struct loader_dri3_drawable *draw) { struct loader_dri3_buffer *buffer; int buf_id; __DRIcontext *dri_context; dri_context = draw->vtable->get_dri_context(draw); if (buffer_type == loader_dri3_buffer_back) { buf_id = dri3_find_back(draw); if (buf_id < 0) return NULL; } else { buf_id = LOADER_DRI3_FRONT_ID; } buffer = draw->buffers[buf_id]; /* Allocate a new buffer if there isn't an old one, or if that * old one is the wrong size */ if (!buffer || buffer->width != draw->width || buffer->height != draw->height) { struct loader_dri3_buffer *new_buffer; /* Allocate the new buffers */ new_buffer = dri3_alloc_render_buffer(draw, format, draw->width, draw->height, draw->depth); if (!new_buffer) return NULL; /* When resizing, copy the contents of the old buffer, waiting for that * copy to complete using our fences before proceeding */ switch (buffer_type) { case loader_dri3_buffer_back: if (buffer) { if (!buffer->linear_buffer) { dri3_fence_reset(draw->conn, new_buffer); dri3_fence_await(draw->conn, buffer); dri3_copy_area(draw->conn, buffer->pixmap, new_buffer->pixmap, dri3_drawable_gc(draw), 0, 0, 0, 0, draw->width, draw->height); dri3_fence_trigger(draw->conn, new_buffer); } else if (draw->vtable->in_current_context(draw)) { draw->ext->image->blitImage(dri_context, new_buffer->image, buffer->image, 0, 0, draw->width, draw->height, 0, 0, draw->width, draw->height, 0); } dri3_free_render_buffer(draw, buffer); } break; case loader_dri3_buffer_front: dri3_fence_reset(draw->conn, new_buffer); dri3_copy_area(draw->conn, draw->drawable, new_buffer->pixmap, dri3_drawable_gc(draw), 0, 0, 0, 0, draw->width, draw->height); dri3_fence_trigger(draw->conn, new_buffer); if (new_buffer->linear_buffer && draw->vtable->in_current_context(draw)) { dri3_fence_await(draw->conn, new_buffer); draw->ext->image->blitImage(dri_context, new_buffer->image, new_buffer->linear_buffer, 0, 0, draw->width, draw->height, 0, 0, draw->width, draw->height, 0); } break; } buffer = new_buffer; buffer->buffer_type = buffer_type; draw->buffers[buf_id] = buffer; } dri3_fence_await(draw->conn, buffer); /* Return the requested buffer */ return buffer; }