00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 #ifdef __HAVE_KMS__
00034 
00035 #include <unistd.h>
00036 #include <stdio.h>
00037 #include <stdlib.h>
00038 #include <errno.h>
00039 #include <string.h>
00040 #include <strings.h>
00041 #include <fcntl.h>
00042 #include <sys/ioctl.h>
00043 #include <sys/mman.h>
00044 #include <sys/kd.h>
00045 #include "mmsgui/fb/mmskms.h"
00046 #include "mmsgui/fb/mmsfbconv.h"
00047 #include "mmsgui/fb/fb.h"
00048 
00049 #define INITCHECK  if(!this->isinitialized){MMSFB_SetError(0,"MMSKms is not initialized");return false;}
00050 
00051 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
00052 
00053 static void page_flip_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void *data)
00054 {
00055     int *waiting_for_flip = (int*)data;
00056     *waiting_for_flip = 0;
00057 }
00058 
00059 MMSKms::MMSKms() {
00060     
00061     this->isinitialized = false;
00062     this->framebuffer_base = NULL;
00063     this->drm.fd = -1;
00064     memset(this->layers, 0, sizeof(this->layers));
00065     this->layers_cnt = 0;
00066     this->active_screen = 0;
00067 
00068     if (MMSFBBase_rotate180) {
00069         this->rotate180 = true;
00070         MMSFBBase_rotate180 = false;
00071     } else {
00072         this->rotate180 = false;
00073     }
00074 
00075 }
00076 
00077 MMSKms::~MMSKms() {
00078     closeDevice();
00079 }
00080 
00081 
00082 void MMSKms::dump_blob(uint32_t blob_id)
00083 {
00084         uint32_t i;
00085         unsigned char *blob_data;
00086         drmModePropertyBlobPtr blob;
00087 
00088         blob = drmModeGetPropertyBlob(this->drm.fd, blob_id);
00089         if (!blob)
00090                 return;
00091 
00092         blob_data = (unsigned char *)blob->data;
00093 
00094         for (i = 0; i < blob->length; i++) {
00095                 if (i % 16 == 0)
00096                         printf("\n\t\t\t");
00097                 printf("%.2hhx", blob_data[i]);
00098         }
00099         printf("\n");
00100 
00101         drmModeFreePropertyBlob(blob);
00102 }
00103 
00104 
00105 void MMSKms::dump_prop(uint32_t prop_id, uint64_t value)
00106 {
00107         int i;
00108         drmModePropertyPtr prop;
00109 
00110         prop = drmModeGetProperty(this->drm.fd, prop_id);
00111 
00112         printf("\t%d", prop_id);
00113         if (!prop) {
00114                 printf("\n");
00115                 return;
00116         }
00117 
00118         printf(" %s:\n", prop->name);
00119 
00120         printf("\t\tflags:");
00121         if (prop->flags & DRM_MODE_PROP_PENDING)
00122                 printf(" pending");
00123         if (prop->flags & DRM_MODE_PROP_RANGE)
00124                 printf(" range");
00125         if (prop->flags & DRM_MODE_PROP_IMMUTABLE)
00126                 printf(" immutable");
00127         if (prop->flags & DRM_MODE_PROP_ENUM)
00128                 printf(" enum");
00129         if (prop->flags & DRM_MODE_PROP_BITMASK)
00130                 printf(" bitmask");
00131         if (prop->flags & DRM_MODE_PROP_BLOB)
00132                 printf(" blob");
00133         printf("\n");
00134 
00135         if (prop->flags & DRM_MODE_PROP_RANGE) {
00136                 printf("\t\tvalues:");
00137                 for (i = 0; i < prop->count_values; i++)
00138                         printf(" %llu", prop->values[i]);
00139                 printf("\n");
00140         }
00141 
00142         if (prop->flags & DRM_MODE_PROP_ENUM) {
00143                 printf("\t\tenums:");
00144                 for (i = 0; i < prop->count_enums; i++)
00145                         printf(" %s=%llu", prop->enums[i].name,
00146                                prop->enums[i].value);
00147                 printf("\n");
00148         } else if (prop->flags & DRM_MODE_PROP_BITMASK) {
00149                 printf("\t\tvalues:");
00150                 for (i = 0; i < prop->count_enums; i++)
00151                         printf(" %s=0x%llx", prop->enums[i].name,
00152                                (1LL << prop->enums[i].value));
00153                 printf("\n");
00154         } else {
00155         }
00156 
00157         if (prop->flags & DRM_MODE_PROP_BLOB) {
00158                 printf("\t\tblobs:\n");
00159                 for (i = 0; i < prop->count_blobs; i++)
00160                         dump_blob(prop->blob_ids[i]);
00161                 printf("\n");
00162         } else {
00163         }
00164 
00165         printf("\t\tvalue:");
00166         if (prop->flags & DRM_MODE_PROP_BLOB)
00167                 dump_blob(value);
00168         else
00169                 printf(" %llu\n", value);
00170 
00171         drmModeFreeProperty(prop);
00172 }
00173 
00174 bool MMSKms::init_drm()
00175 {
00176     static const char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "omapdrm", "exynos" };
00177     drmModeRes *resources;
00178     drmModeConnector *connector = NULL;
00179     drmModeEncoder *encoder = NULL;
00180     int i, area;
00181 
00182     for (i = 0; i < ARRAY_SIZE(modules); i++) {
00183         printf("trying to load module %s...", modules[i]);
00184         this->drm.fd = drmOpen(modules[i], NULL);
00185 
00186         if (this->drm.fd < 0) {
00187             printf("failed.\n");
00188         } else {
00189             printf("success.\n");
00190             break;
00191         }
00192     }
00193 
00194     if (this->drm.fd < 0) {
00195         printf("could not open drm device\n");
00196         return false;
00197     }
00198 
00199     resources = drmModeGetResources(this->drm.fd);
00200     if (!resources) {
00201         printf("drmModeGetResources failed: %s\n", strerror(errno));
00202         drmClose(this->drm.fd);
00203         this->drm.fd = -1;
00204         return false;
00205     }
00206 
00207     
00208     for (i = 0; i < resources->count_connectors; i++) {
00209         connector = drmModeGetConnector(this->drm.fd, resources->connectors[i]);
00210 
00211         if (connector->connection == DRM_MODE_CONNECTED) {
00212             
00213             break;
00214         }
00215 
00216         drmModeFreeConnector(connector);
00217         connector = NULL;
00218     }
00219 
00220     if (!connector) {
00221         
00222 
00223 
00224         printf("no connected connector!\n");
00225         drmClose(this->drm.fd);
00226         this->drm.fd = -1;
00227         return false;
00228     }
00229 
00230     
00231     for (i = 0, area = 0; i < connector->count_modes; i++) {
00232         drmModeModeInfo *current_mode = &connector->modes[i];
00233 
00234         int current_area = current_mode->hdisplay * current_mode->vdisplay;
00235 
00236         if (current_area > area) {
00237             this->drm.mode = current_mode;
00238             area = current_area;
00239         }
00240     }
00241 
00242     if (!this->drm.mode) {
00243         printf("could not find mode!\n");
00244         drmClose(this->drm.fd);
00245         this->drm.fd = -1;
00246         return false;
00247     }
00248 
00249     
00250     for (i = 0; i < resources->count_encoders; i++) {
00251         encoder = drmModeGetEncoder(this->drm.fd, resources->encoders[i]);
00252 
00253         if (encoder->encoder_id == connector->encoder_id)
00254             break;
00255 
00256         drmModeFreeEncoder(encoder);
00257         encoder = NULL;
00258     }
00259 
00260     if (!encoder) {
00261         printf("no encoder!\n");
00262         drmClose(this->drm.fd);
00263         this->drm.fd = -1;
00264         return false;
00265     }
00266 
00267     this->drm.crtc_id = encoder->crtc_id;
00268     this->drm.connector_id = connector->connector_id;
00269 
00270     if (this->rotate180) {
00271         drmModeObjectSetProperty(this->drm.fd, encoder->crtc_id, DRM_MODE_OBJECT_CRTC, 8, 4);
00272     }
00273 
00274 
00275 
00276 
00277 
00278 
00279 
00280 
00281 
00282 
00283 
00284 
00285 
00286 
00287 
00288 
00289 
00290 
00291 
00292     drmModePlaneRes *plane_resources;
00293     drmModePlane *ovr;
00294 
00295     plane_resources = drmModeGetPlaneResources(this->drm.fd);
00296     if (!plane_resources) {
00297             fprintf(stderr, "drmModeGetPlaneResources failed: %s\n",
00298                     strerror(errno));
00299             return false;
00300     }
00301 
00302 
00303 
00304     for (i = 0; i < plane_resources->count_planes; i++) {
00305             ovr = drmModeGetPlane(this->drm.fd, plane_resources->planes[i]);
00306             if (!ovr) {
00307                     fprintf(stderr, "drmModeGetPlane failed: %s\n",
00308                             strerror(errno));
00309                     continue;
00310             }
00311 
00312 
00313 
00314 
00315 
00316 
00317 
00318 
00319 
00320 
00321 
00322 
00323 
00324 
00325 
00326 
00327 
00328 
00329 
00330 
00331 
00332 
00333 
00334 
00335 
00336 
00337 
00338             if (ovr->possible_crtcs & this->drm.crtc_id){
00339                     this->drm.plane_id = ovr->plane_id;
00340                     break;
00341             }
00342 
00343 
00344     }
00345 
00346 
00347 
00348     return true;
00349 }
00350 
00351 bool MMSKms::init_gbm()
00352 {
00353     this->drm.dev = gbm_create_device(this->drm.fd);
00354 
00355     if (!init_omap()) {
00356         printf("failed to initialize OMAP\n");
00357         return false;
00358     }
00359 
00360 
00361 
00362     
00363     
00364     
00365     
00366     
00367     
00368     
00369 
00370     if (outputtype == MMSFB_OT_OGL) {
00371         this->drm.surface = gbm_surface_create(this->drm.dev, this->drm.mode->hdisplay, this->drm.mode->vdisplay,
00372                             GBM_FORMAT_ARGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
00373 
00374         if (!this->drm.surface) {
00375             printf("failed to create gbm surface\n");
00376             drmClose(this->drm.fd);
00377             this->drm.fd = -1;
00378             return false;
00379         }
00380 
00381         this->bo = gbm_surface_lock_front_buffer(this->drm.surface);
00382         this->fb = (DRM_FB*)drm_fb_get_from_bo(this->bo);
00383         gbm_surface_release_buffer(this->drm.surface, this->bo);
00384     }
00385 
00386     return true;
00387 }
00388 
00389 static void
00390 drm_fb_destroy_callback(struct gbm_bo *bo, void *data)
00391 {
00392     DRM_FB *fb = (DRM_FB*)data;
00393     struct gbm_device *gbm = gbm_bo_get_device(bo);
00394     if(gbm) {
00395         int fd = gbm_device_get_fd(gbm);
00396         if (fb->fb_id)
00397             drmModeRmFB(fd, fb->fb_id);
00398     }
00399 
00400     free(fb);
00401 }
00402 
00403 DRM_FB* MMSKms::drm_fb_get_from_bo(struct gbm_bo *bo)
00404 {
00405     DRM_FB *fb = (DRM_FB*)gbm_bo_get_user_data(bo);
00406     uint32_t width, height, stride, handle;
00407     int ret;
00408 
00409     if (fb)
00410         return fb;
00411 
00412     fb = (DRM_FB*)calloc(1, sizeof *fb);
00413     fb->bo = bo;
00414 
00415     width = gbm_bo_get_width(bo);
00416     height = gbm_bo_get_height(bo);
00417     stride = gbm_bo_get_stride(bo);
00418     handle = gbm_bo_get_handle(bo).u32;
00419 
00420     ret = drmModeAddFB(this->drm.fd, width, height, 24, 32, stride, handle, &fb->fb_id);
00421     if (ret) {
00422         printf("failed to create fb: %s\n", strerror(errno));
00423         free(fb);
00424         return NULL;
00425     }
00426 
00427     ret =0;
00428     ret = drmModeSetCrtc(this->drm.fd, this->drm.crtc_id, fb->fb_id, 0, 0,
00429                         &this->drm.connector_id, 1, this->drm.mode);
00430 
00431     if (ret) {
00432         printf("failed to set mode: %s\n", strerror(errno));
00433     }
00434 
00435     if (this->rotate180) {
00436         drmModeObjectSetProperty(this->drm.fd, this->drm.plane_id, DRM_MODE_OBJECT_PLANE, 8, 4);
00437     }
00438 
00439     if ((this->drm.width != this->drm.mode->hdisplay) || (this->drm.height != this->drm.mode->vdisplay)) {
00440         ret = drmModeSetPlane(this->drm.fd, this->drm.plane_id, this->drm.crtc_id,
00441                 fb->fb_id, 0, 0, 0, this->drm.mode->hdisplay, this->drm.mode->vdisplay,
00442                 0, (this->drm.mode->vdisplay-this->drm.height) << 16, this->drm.width << 16, this->drm.height << 16);
00443 
00444         if (ret)
00445             printf("drmModeSetPlane failed\n");
00446     }
00447 
00448     gbm_bo_set_user_data(bo, fb, drm_fb_destroy_callback);
00449 
00450     return fb;
00451 }
00452 
00453 bool MMSKms::init_omap()
00454 {
00455     this->drm.o_dev = omap_device_new(this->drm.fd);
00456 
00457     if (!this->drm.dev) {
00458         printf("ERROR:couldn't create omap device\n");
00459         return false;
00460     }
00461 
00462     uint32_t bo_flags = OMAP_BO_TILED_32 | OMAP_BO_SCANOUT | OMAP_BO_WC;
00463 
00464     if (bo_flags & OMAP_BO_TILED) {
00465         this->o_bo = omap_bo_new_tiled(this->drm.o_dev, this->drm.mode->hdisplay, this->drm.mode->vdisplay, bo_flags);
00466     } else {
00467         this->o_bo = omap_bo_new(this->drm.o_dev, this->drm.mode->hdisplay * this->drm.mode->vdisplay * 32 / 8, bo_flags);
00468     }
00469 
00470     if (!this->o_bo) {
00471         printf("failed to create omap bo\n");
00472         drmClose(this->drm.fd);
00473         this->drm.fd = -1;
00474         return false;
00475     }
00476 
00477 
00478     uint32_t handle;
00479     int ret;
00480 
00481     this->fb = (DRM_FB*)calloc(1, sizeof *this->fb);
00482 
00483     unsigned int alignedWidth;
00484     alignedWidth = (this->drm.mode->hdisplay + (32 - 1)) & ~(32 - 1);
00485     this->stride = ((alignedWidth * 32) + 7) / 8;
00486     if (bo_flags & OMAP_BO_TILED)
00487         this->stride = (stride + (4096 - 1)) & ~(4096 - 1);
00488 
00489     handle = omap_bo_handle(this->o_bo);
00490 
00491     ret = drmModeAddFB(this->drm.fd, this->drm.mode->hdisplay, this->drm.mode->vdisplay, 24, 32, this->stride, handle, &fb->fb_id);
00492     if (ret) {
00493         printf("failed to create fb: %s\n", strerror(errno));
00494         free(this->fb);
00495         return false;
00496     }
00497 
00498 
00499     this->framebuffer_base = omap_bo_map(this->o_bo);
00500 
00501 
00502     return true;
00503 }
00504 
00505 bool MMSKms::openDevice(MMSFBOutputType outputtype) {
00506     
00507     this->outputtype = outputtype;
00508     closeDevice();
00509 
00510     if (!init_drm()) {
00511         printf("failed to initialize DRM\n");
00512         return false;
00513     }
00514 
00515     if (!init_gbm()) {
00516         printf("failed to initialize GBM\n");
00517         return false;
00518     }
00519 
00520     memset(&this->evctx, 0, sizeof(this->evctx));
00521     this->evctx.version = DRM_EVENT_CONTEXT_VERSION;
00522     this->evctx.page_flip_handler = page_flip_handler;
00523 
00524     
00525     this->isinitialized = true;
00526 
00527     return true;
00528 }
00529 
00530 void MMSKms::closeDevice() {
00531 
00532     if (this->drm.fd != -1) {
00533         drmClose(this->drm.fd);
00534         this->drm.fd = -1;
00535     }
00536 
00537     
00538     this->isinitialized = false;
00539     memset(this->layers, 0, sizeof(this->layers));
00540     this->layers_cnt = 0;
00541     this->active_screen = 0;
00542 }
00543 
00544 bool MMSKms::isInitialized() {
00545     return this->isinitialized;
00546 }
00547 
00548 bool MMSKms::panDisplay(int buffer_id, void *framebuffer_base) {
00549     
00550     INITCHECK;
00551 
00552     
00553     if (framebuffer_base) {
00554         if (framebuffer_base != this->framebuffer_base) {
00555             printf("MMSFBDev: framebuffer base pointer not correct\n");
00556             return false;
00557         }
00558     }
00559 
00560     fd_set fds;
00561     FD_ZERO(&fds);
00562     FD_SET(0, &fds);
00563     FD_SET(this->drm.fd, &fds);
00564 
00565     int waiting_for_flip = 1;
00566     int ret = 0;
00567 
00568     printf("MMSKMS: page flip (pan display)\n");
00569 
00570     ret = drmModePageFlip(this->drm.fd, this->drm.crtc_id, this->fb->fb_id, DRM_MODE_PAGE_FLIP_EVENT, &waiting_for_flip);
00571     if (ret) {
00572         printf("OPENGL_SWAP: failed to queue page flip\n");
00573         return false;
00574     }
00575 
00576     while (waiting_for_flip) {
00577         ret = select(this->drm.fd + 1, &fds, NULL, NULL, NULL);
00578         if (ret < 0) {
00579             printf("OPENGL_SWAP: select err\n");
00580             return false;
00581         } else if (ret == 0) {
00582             printf("OPENGL_SWAP: select timeout!\n");
00583             return false;
00584         } else if (FD_ISSET(0, &fds)) {
00585             printf("OPENGL_SWAP: user interrupted!\n");
00586             break;
00587         }
00588         drmHandleEvent(this->drm.fd, &this->evctx);
00589     }
00590 
00591     return true;
00592 }
00593 
00594 bool MMSKms::testLayer(int layer_id) {
00595     
00596     INITCHECK;
00597 
00598     
00599     if (layer_id != 0) {
00600         printf("MMSKms: layer %d is not supported\n", layer_id);
00601         return false;
00602     }
00603 
00604     return true;
00605 }
00606 
00607 bool MMSKms::initLayer(int layer_id, int width, int height, MMSFBSurfacePixelFormat pixelformat, int backbuffer) {
00608     
00609     INITCHECK;
00610 
00611 
00612 
00613     this->drm.width = width;
00614     this->drm.height = height;
00615 
00616     
00617     if (layer_id != 0) {
00618         printf("MMSKms: layer %d is not supported\n", layer_id);
00619         return false;
00620     }
00621 
00622     int ret =0;
00623 
00624     
00625     ret = 0;
00626     ret = drmModeSetCrtc(this->drm.fd, this->drm.crtc_id, this->fb->fb_id, 0, 0,
00627                         &this->drm.connector_id, 1, this->drm.mode);
00628 
00629     if (ret) {
00630         printf("failed to set mode: %s\n", strerror(errno));
00631         return false;
00632     }
00633 
00634     if (this->rotate180) {
00635         drmModeObjectSetProperty(this->drm.fd, this->drm.plane_id, DRM_MODE_OBJECT_PLANE, 8, 4);
00636     }
00637 
00638     if ((this->drm.width != this->drm.mode->hdisplay) || (this->drm.height != this->drm.mode->vdisplay)) {
00639         ret = drmModeSetPlane(this->drm.fd, this->drm.plane_id, this->drm.crtc_id,
00640                 this->fb->fb_id, 0, 0, 0, this->drm.mode->hdisplay, this->drm.mode->vdisplay,
00641                 0, 0, this->drm.width << 16, this->drm.height << 16);
00642 
00643         if (ret)
00644             printf("drmModeSetPlane failed\n");
00645     }
00646 
00647     if (width <= 0 || height <= 0) {
00648         
00649         this->layers[layer_id].isinitialized = false;
00650         return true;
00651     }
00652 
00653     
00654     this->layers[layer_id].width = width;
00655     this->layers[layer_id].height = height;
00656     this->layers[layer_id].pixelformat = pixelformat;
00657 
00658     
00659     memset(&this->layers[layer_id].buffers, 0, sizeof(this->layers[layer_id].buffers));
00660 
00661     this->layers[layer_id].buffers[0].ptr  = this->framebuffer_base;
00662     this->layers[layer_id].buffers[0].pitch= this->stride;
00663     this->layers[layer_id].buffers[0].hwbuffer = true;
00664 
00665     
00666     this->layers[layer_id].isinitialized = true;
00667 
00668     
00669     this->active_screen = 0;
00670 
00671     return true;
00672 }
00673 
00674 bool MMSKms::releaseLayer(int layer_id) {
00675     printf("MMSKms: layer %d cannot be released\n", layer_id);
00676     return false;
00677 }
00678 
00679 bool MMSKms::restoreLayer(int layer_id) {
00680     printf("MMSKms: layer %d cannot be restored\n", layer_id);
00681     return false;
00682 }
00683 
00684 bool MMSKms::getPixelFormat(int layer_id, MMSFBSurfacePixelFormat *pf) {
00685     
00686     INITCHECK;
00687 
00688     
00689     if (!this->layers[layer_id].isinitialized)
00690         return false;
00691 
00692     
00693     *pf = this->layers[layer_id].pixelformat;
00694     return true;
00695 }
00696 
00697 bool MMSKms::getFrameBufferPtr(int layer_id, MMSFBSurfacePlanesBuffer buffers, int *width, int *height) {
00698     
00699     INITCHECK;
00700 
00701     
00702     if (!this->layers[layer_id].isinitialized) {
00703         return false;
00704     }
00705 
00706     
00707     if (buffers)
00708         memcpy(buffers, this->layers[layer_id].buffers, sizeof(this->layers[layer_id].buffers));
00709     *width = this->layers[layer_id].width;
00710     *height = this->layers[layer_id].height;
00711 
00712     return true;
00713 }
00714 
00715 
00716 void MMSKms::genFBPixelFormat(MMSFBSurfacePixelFormat pf, unsigned int *nonstd_format, MMSFBPixelDef *pixeldef) {
00717 
00718     
00719     if (nonstd_format) *nonstd_format = 0;
00720     getBitsPerPixel(pf, pixeldef);
00721 
00722     
00723     this->onGenFBPixelFormat.emit(pf, nonstd_format, pixeldef);
00724 }
00725 
00726 DRM *MMSKms::getDrm() {
00727     return &(this->drm);
00728 }
00729 
00730 void MMSKms::pageFlip() {
00731 
00732     fd_set fds;
00733     FD_ZERO(&fds);
00734     FD_SET(0, &fds);
00735     FD_SET(this->drm.fd, &fds);
00736 
00737     DRM_FB *my_fb;
00738     struct gbm_bo *next_bo;
00739     int waiting_for_flip = 1;
00740 
00741     next_bo = gbm_surface_lock_front_buffer(this->drm.surface);
00742     my_fb = (DRM_FB*)drm_fb_get_from_bo(next_bo);
00743 
00744 
00745 
00746     int ret =0;
00747 
00748 
00749 
00750 
00751 
00752 
00753 
00754 
00755 
00756 
00757 
00758 
00759 
00760 
00761 
00762 
00763 
00764 
00765 
00766 
00767     ret = 0;
00768     ret = drmModePageFlip(this->drm.fd, this->drm.crtc_id, my_fb->fb_id,    DRM_MODE_PAGE_FLIP_EVENT, &waiting_for_flip);
00769     if (ret) {
00770         printf("OPENGL_SWAP: failed to queue page flip\n");
00771         return;
00772     }
00773 
00774     while (waiting_for_flip) {
00775         ret = select(this->drm.fd + 1, &fds, NULL, NULL, NULL);
00776         if (ret < 0) {
00777             printf("OPENGL_SWAP: select err\n");
00778             return;
00779         } else if (ret == 0) {
00780             printf("OPENGL_SWAP: select timeout!\n");
00781             return;
00782         } else if (FD_ISSET(0, &fds)) {
00783             printf("OPENGL_SWAP: user interrupted!\n");
00784             break;
00785         }
00786         drmHandleEvent(this->drm.fd, &this->evctx);
00787     }
00788 
00789     gbm_surface_release_buffer(this->drm.surface, next_bo);
00790 
00791 }
00792 
00793 #endif