#include "gralloc_drm.h"
#include "gralloc_drm_priv.h"
+#include <drm_fourcc.h>
+
/*
* Return true if a bo needs fb.
*/
}
/*
+ * Modify pitches, offsets and handles according to
+ * the format and return corresponding drm format value
+ */
+static int resolve_drm_format(struct gralloc_drm_bo_t *bo,
+ uint32_t *pitches, uint32_t *offsets, uint32_t *handles)
+{
+ memset(pitches, 0, 4 * sizeof(uint32_t));
+ memset(offsets, 0, 4 * sizeof(uint32_t));
+ memset(handles, 0, 4 * sizeof(uint32_t));
+
+ pitches[0] = bo->handle->stride;
+ handles[0] = bo->fb_handle;
+
+ switch(bo->handle->format) {
+ case HAL_PIXEL_FORMAT_RGB_888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ return DRM_FORMAT_ARGB8888;
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ return DRM_FORMAT_RGBA8888;
+ case HAL_PIXEL_FORMAT_RGB_565:
+ return DRM_FORMAT_RGB565;
+ case HAL_PIXEL_FORMAT_YV12:
+
+ // U and V stride are half of Y plane
+ pitches[2] = pitches[0]/2;
+ pitches[1] = pitches[0]/2;
+
+ // like I420 but U and V are in reverse order
+ offsets[2] = offsets[0] +
+ pitches[0] * bo->handle->height;
+ offsets[1] = offsets[2] +
+ pitches[2] * bo->handle->height/2;
+
+ handles[1] = handles[2] = handles[0];
+
+ return DRM_FORMAT_YUV420;
+ default:
+ return 0;
+ }
+ return 0;
+}
+
+/*
* Add a fb object for a bo.
*/
int gralloc_drm_bo_add_fb(struct gralloc_drm_bo_t *bo)
{
- uint8_t bpp;
+ uint32_t pitches[4];
+ uint32_t offsets[4];
+ uint32_t handles[4];
if (bo->fb_id)
return 0;
- bpp = gralloc_drm_get_bpp(bo->handle->format) * 8;
+ int drm_format = resolve_drm_format(bo, pitches, offsets, handles);
+
+ if (drm_format == 0) {
+ ALOGE("error resolving drm format");
+ return -EINVAL;
+ }
- return drmModeAddFB(bo->drm->fd,
- bo->handle->width, bo->handle->height, bpp, bpp,
- bo->handle->stride, bo->fb_handle,
- (uint32_t *) &bo->fb_id);
+ return drmModeAddFB2(bo->drm->fd,
+ bo->handle->width, bo->handle->height,
+ drm_format, handles, pitches, offsets,
+ (uint32_t *) &bo->fb_id, 0);
}
/*
drm->fb_format,
GRALLOC_USAGE_HW_FB);
if (front && gralloc_drm_bo_add_fb(front)) {
- gralloc_drm_bo_destroy(front);
+ gralloc_drm_bo_decref(front);
front = NULL;
}
return -EINVAL;
}
+ drm->plane_resources = drmModeGetPlaneResources(drm->fd);
+ if (!drm->plane_resources) {
+ ALOGD("no planes found from drm resources");
+ } else {
+ ALOGD("supported drm planes and formats");
+ /* fill a helper structure for hwcomposer */
+ drm->planes = calloc(drm->plane_resources->count_planes,
+ sizeof(struct gralloc_drm_plane_t));
+
+ for (i = 0; i < drm->plane_resources->count_planes; i++) {
+
+ unsigned int j;
+
+ drm->planes[i].drm_plane = drmModeGetPlane(drm->fd,
+ drm->plane_resources->planes[i]);
+
+ ALOGD("plane id %d", drm->planes[i].drm_plane->plane_id);
+ for (j = 0; j < drm->planes[i].drm_plane->count_formats; j++)
+ ALOGD(" format %c%c%c%c",
+ (drm->planes[i].drm_plane->formats[j]),
+ (drm->planes[i].drm_plane->formats[j])>>8,
+ (drm->planes[i].drm_plane->formats[j])>>16,
+ (drm->planes[i].drm_plane->formats[j])>>24);
+ }
+ }
+
/* find the crtc/connector/mode to use */
for (i = 0; i < drm->resources->count_connectors; i++) {
drmModeConnectorPtr connector;
&drm->current_front : &drm->next_front;
if (*bo)
- gralloc_drm_bo_destroy(*bo);
+ gralloc_drm_bo_decref(*bo);
*bo = NULL;
}
break;
drm->resources = NULL;
}
+ if (drm->planes) {
+ unsigned int i;
+ for (i = 0; i < drm->plane_resources->count_planes; i++)
+ drmModeFreePlane(drm->planes[i].drm_plane);
+ free(drm->planes);
+ drm->planes = NULL;
+ }
+
+ if (drm->plane_resources) {
+ drmModeFreePlaneResources(drm->plane_resources);
+ drm->plane_resources = NULL;
+ }
+
drm_singleton = NULL;
}