static struct native_surface * android_display_create_window_surface(struct native_display *ndpy, EGLNativeWindowType win, const struct native_config *nconf) { struct android_display *adpy = android_display(ndpy); struct android_config *aconf = android_config(nconf); struct android_surface *asurf; enum pipe_format format; int val; if (win->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) { LOGE("invalid native window with magic 0x%x", win->common.magic); return NULL; } if (win->query(win, NATIVE_WINDOW_FORMAT, &val)) { LOGE("failed to query native window format"); return NULL; } format = get_pipe_format(val); if (format != nconf->color_format) { LOGW("native window format 0x%x != config format 0x%x", format, nconf->color_format); if (!adpy->base.screen->is_format_supported(adpy->base.screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET)) { LOGE("and the native window cannot be used as a render target"); return NULL; } } asurf = CALLOC_STRUCT(android_surface); if (!asurf) return NULL; asurf->adpy = adpy; asurf->win = win; asurf->win->common.incRef(&asurf->win->common); /* request buffers that are for CPU access */ if (!adpy->use_drm) { native_window_set_usage(asurf->win, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); } asurf->base.destroy = android_surface_destroy; asurf->base.present = android_surface_present; asurf->base.validate = android_surface_validate; asurf->base.wait = android_surface_wait; return &asurf->base; }
static boolean android_display_init_configs(struct native_display *ndpy) { struct android_display *adpy = android_display(ndpy); const int native_formats[] = { HAL_PIXEL_FORMAT_RGBA_8888, HAL_PIXEL_FORMAT_RGBX_8888, HAL_PIXEL_FORMAT_RGB_888, HAL_PIXEL_FORMAT_RGB_565, HAL_PIXEL_FORMAT_BGRA_8888, }; int i; adpy->configs = (struct android_config *) CALLOC(Elements(native_formats), sizeof(*adpy->configs)); if (!adpy->configs) return FALSE; for (i = 0; i < Elements(native_formats); i++) { enum pipe_format color_format; struct android_config *aconf; color_format = get_pipe_format(native_formats[i]); if (color_format == PIPE_FORMAT_NONE || !adpy->base.screen->is_format_supported(adpy->base.screen, color_format, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET)) { LOGI("skip unsupported native format 0x%x", native_formats[i]); continue; } aconf = &adpy->configs[adpy->num_configs++]; /* only the back buffer */ aconf->base.buffer_mask = 1 << NATIVE_ATTACHMENT_BACK_LEFT; aconf->base.color_format = color_format; aconf->base.window_bit = TRUE; aconf->base.native_visual_id = native_formats[i]; aconf->base.native_visual_type = native_formats[i]; } return TRUE; }
static struct pipe_resource * android_display_import_buffer(struct native_display *ndpy, struct native_buffer *nbuf) { struct android_display *adpy = android_display(ndpy); ANativeWindowBuffer *abuf; enum pipe_format format; struct pipe_resource templ; if (nbuf->type != NATIVE_BUFFER_ANDROID) return NULL; abuf = nbuf->u.android; if (!abuf || abuf->common.magic != ANDROID_NATIVE_BUFFER_MAGIC || abuf->common.version != sizeof(*abuf)) { LOGE("invalid android native buffer"); return NULL; } format = get_pipe_format(abuf->format); if (format == PIPE_FORMAT_NONE) return NULL; memset(&templ, 0, sizeof(templ)); templ.target = PIPE_TEXTURE_2D; templ.format = format; /* assume for texturing only */ templ.bind = PIPE_BIND_SAMPLER_VIEW; templ.width0 = abuf->width; templ.height0 = abuf->height; templ.depth0 = 1; templ.array_size = 1; return import_buffer(adpy, &templ, abuf); }
static struct pipe_resource * android_surface_add_cache(struct native_surface *nsurf, ANativeWindowBuffer *abuf) { struct android_surface *asurf = android_surface(nsurf); void *handle; int idx; /* how about abuf->usage? */ if (asurf->cache_key.width != abuf->width || asurf->cache_key.height != abuf->height || asurf->cache_key.format != abuf->format) android_surface_clear_cache(&asurf->base); if (asurf->adpy->use_drm) handle = (void *) get_handle_name(abuf->handle); else handle = (void *) abuf->handle; /* NULL is invalid */ if (!handle) { LOGE("invalid buffer native buffer %p", abuf); return NULL; } /* find the slot to use */ for (idx = 0; idx < Elements(asurf->cache_handles); idx++) { if (asurf->cache_handles[idx] == handle || !asurf->cache_handles[idx]) break; } if (idx == Elements(asurf->cache_handles)) { LOGW("cache full: buf %p, width %d, height %d, format %d, usage 0x%x", abuf, abuf->width, abuf->height, abuf->format, abuf->usage); android_surface_clear_cache(&asurf->base); idx = 0; } if (idx == 0) { asurf->cache_key.width = abuf->width; asurf->cache_key.height = abuf->height; asurf->cache_key.format = abuf->format; } if (!asurf->cache_handles[idx]) { struct pipe_resource templ; assert(!asurf->cache_resources[idx]); memset(&templ, 0, sizeof(templ)); templ.target = PIPE_TEXTURE_2D; templ.format = get_pipe_format(asurf->buf->format); templ.bind = PIPE_BIND_RENDER_TARGET; if (!asurf->adpy->use_drm) { templ.bind |= PIPE_BIND_TRANSFER_WRITE | PIPE_BIND_TRANSFER_READ; } templ.width0 = asurf->buf->width; templ.height0 = asurf->buf->height; templ.depth0 = 1; templ.array_size = 1; if (templ.format != PIPE_FORMAT_NONE) { asurf->cache_resources[idx] = import_buffer(asurf->adpy, &templ, asurf->buf); } else { asurf->cache_resources[idx] = NULL; } asurf->cache_handles[idx] = handle; } return asurf->cache_resources[idx]; }
static struct pipe_buffer *get_pipe_buffer_locked(struct pipe_manager *pm, const struct gralloc_drm_handle_t *handle) { struct pipe_buffer *buf; struct pipe_resource templ; memset(&templ, 0, sizeof(templ)); templ.format = get_pipe_format(handle->format); templ.bind = get_pipe_bind(handle->usage); templ.target = PIPE_TEXTURE_2D; if (templ.format == PIPE_FORMAT_NONE || !pm->screen->is_format_supported(pm->screen, templ.format, templ.target, 0, templ.bind)) { LOGE("unsupported format 0x%x", handle->format); return NULL; } buf = CALLOC(1, sizeof(*buf)); if (!buf) { LOGE("failed to allocate pipe buffer"); return NULL; } templ.width0 = handle->width; templ.height0 = handle->height; templ.depth0 = 1; templ.array_size = 1; if (handle->name) { buf->winsys.type = DRM_API_HANDLE_TYPE_SHARED; buf->winsys.handle = handle->name; buf->winsys.stride = handle->stride; buf->resource = pm->screen->resource_from_handle(pm->screen, &templ, &buf->winsys); if (!buf->resource) goto fail; } else { buf->resource = pm->screen->resource_create(pm->screen, &templ); if (!buf->resource) goto fail; buf->winsys.type = DRM_API_HANDLE_TYPE_SHARED; if (!pm->screen->resource_get_handle(pm->screen, buf->resource, &buf->winsys)) goto fail; } /* need the gem handle for fb */ if (handle->usage & GRALLOC_USAGE_HW_FB) { struct winsys_handle tmp; memset(&tmp, 0, sizeof(tmp)); tmp.type = DRM_API_HANDLE_TYPE_KMS; if (!pm->screen->resource_get_handle(pm->screen, buf->resource, &tmp)) goto fail; buf->base.fb_handle = tmp.handle; } return buf; fail: LOGE("failed to allocate pipe buffer"); if (buf->resource) pipe_resource_reference(&buf->resource, NULL); FREE(buf); return NULL; }