The Android backend provides basic EGL/GLES2 graphics, where everything is always composited. Overlays are not used. Input is stubbed, therefore there is no input yet. This adds the first C++ source file into Weston compositor. The Android gralloc and fb HAL glue code to the Android EGL library is in C++, and there is no way to access it from plain C. We have a simple wrapper to the required C++ class API. Android forces the C++ file name extension to .cpp. The android backend is compiled by default. However, all Android specific calls are protected with #ifdef ANDROID, so it will build also without Android headers. The binary produced without the Android build system is useless, but allows build-testing generic Weston changes. Therefore the android backend is not installed. Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
parent
daed3bc1aa
commit
3ae50bb45c
@ -0,0 +1,93 @@ |
|||||||
|
/*
|
||||||
|
* Copyright © 2012 Collabora, Ltd. |
||||||
|
* |
||||||
|
* Permission to use, copy, modify, distribute, and sell this software and |
||||||
|
* its documentation for any purpose is hereby granted without fee, provided |
||||||
|
* that the above copyright notice appear in all copies and that both that |
||||||
|
* copyright notice and this permission notice appear in supporting |
||||||
|
* documentation, and that the name of the copyright holders not be used in |
||||||
|
* advertising or publicity pertaining to distribution of the software |
||||||
|
* without specific, written prior permission. The copyright holders make |
||||||
|
* no representations about the suitability of this software for any |
||||||
|
* purpose. It is provided "as is" without express or implied warranty. |
||||||
|
* |
||||||
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS |
||||||
|
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND |
||||||
|
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY |
||||||
|
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER |
||||||
|
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF |
||||||
|
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
||||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <cstdlib> |
||||||
|
|
||||||
|
#include "android-framebuffer.h" |
||||||
|
|
||||||
|
#ifdef ANDROID |
||||||
|
|
||||||
|
#include <ui/FramebufferNativeWindow.h> |
||||||
|
|
||||||
|
class AndroidFramebuffer { |
||||||
|
public: |
||||||
|
int init(); |
||||||
|
|
||||||
|
struct android_framebuffer fb_; |
||||||
|
|
||||||
|
private: |
||||||
|
android::sp<android::FramebufferNativeWindow> nativefb_; |
||||||
|
}; |
||||||
|
|
||||||
|
int AndroidFramebuffer::init() |
||||||
|
{ |
||||||
|
struct ANativeWindow *window; |
||||||
|
const framebuffer_device_t *fbdev; |
||||||
|
int ret1, ret2, ret3; |
||||||
|
|
||||||
|
nativefb_ = new android::FramebufferNativeWindow(); |
||||||
|
fbdev = nativefb_->getDevice(); |
||||||
|
|
||||||
|
if (!fbdev) |
||||||
|
return -1; |
||||||
|
|
||||||
|
fb_.priv = this; |
||||||
|
|
||||||
|
window = nativefb_.get(); |
||||||
|
ret1 = window->query(window, NATIVE_WINDOW_WIDTH, &fb_.width); |
||||||
|
ret2 = window->query(window, NATIVE_WINDOW_HEIGHT, &fb_.height); |
||||||
|
ret3 = window->query(window, NATIVE_WINDOW_FORMAT, &fb_.format); |
||||||
|
fb_.xdpi = window->xdpi; |
||||||
|
fb_.ydpi = window->ydpi; |
||||||
|
fb_.refresh_rate = fbdev->fps; |
||||||
|
|
||||||
|
if (ret1 != android::NO_ERROR || |
||||||
|
ret2 != android::NO_ERROR || |
||||||
|
ret3 != android::NO_ERROR) |
||||||
|
return -1; |
||||||
|
|
||||||
|
fb_.native_window = reinterpret_cast<EGLNativeWindowType>(window); |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
void |
||||||
|
android_framebuffer_destroy(struct android_framebuffer *fb) |
||||||
|
{ |
||||||
|
AndroidFramebuffer *afb = static_cast<AndroidFramebuffer*>(fb->priv); |
||||||
|
|
||||||
|
delete afb; |
||||||
|
} |
||||||
|
|
||||||
|
struct android_framebuffer * |
||||||
|
android_framebuffer_create(void) |
||||||
|
{ |
||||||
|
AndroidFramebuffer *afb = new AndroidFramebuffer; |
||||||
|
|
||||||
|
if (afb->init() < 0) { |
||||||
|
delete afb; |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
return &afb->fb_; |
||||||
|
} |
||||||
|
|
||||||
|
#endif /* ANDROID */ |
@ -0,0 +1,54 @@ |
|||||||
|
/*
|
||||||
|
* Copyright © 2012 Collabora, Ltd. |
||||||
|
* |
||||||
|
* Permission to use, copy, modify, distribute, and sell this software and |
||||||
|
* its documentation for any purpose is hereby granted without fee, provided |
||||||
|
* that the above copyright notice appear in all copies and that both that |
||||||
|
* copyright notice and this permission notice appear in supporting |
||||||
|
* documentation, and that the name of the copyright holders not be used in |
||||||
|
* advertising or publicity pertaining to distribution of the software |
||||||
|
* without specific, written prior permission. The copyright holders make |
||||||
|
* no representations about the suitability of this software for any |
||||||
|
* purpose. It is provided "as is" without express or implied warranty. |
||||||
|
* |
||||||
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS |
||||||
|
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND |
||||||
|
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY |
||||||
|
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER |
||||||
|
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF |
||||||
|
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
||||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||||
|
*/ |
||||||
|
|
||||||
|
#ifndef ANDROID_FRAMEBUFFER_H |
||||||
|
#define ANDROID_FRAMEBUFFER_H |
||||||
|
|
||||||
|
#include <EGL/egl.h> |
||||||
|
|
||||||
|
#ifdef __cplusplus |
||||||
|
extern "C" { |
||||||
|
#endif |
||||||
|
|
||||||
|
struct android_framebuffer { |
||||||
|
EGLNativeWindowType native_window; |
||||||
|
int width; |
||||||
|
int height; |
||||||
|
int format; |
||||||
|
float xdpi; |
||||||
|
float ydpi; |
||||||
|
float refresh_rate; |
||||||
|
|
||||||
|
void *priv; |
||||||
|
}; |
||||||
|
|
||||||
|
void |
||||||
|
android_framebuffer_destroy(struct android_framebuffer *fb); |
||||||
|
|
||||||
|
struct android_framebuffer * |
||||||
|
android_framebuffer_create(void); |
||||||
|
|
||||||
|
#ifdef __cplusplus |
||||||
|
} /* extern "C" */ |
||||||
|
#endif |
||||||
|
|
||||||
|
#endif /* ANDROID_FRAMEBUFFER_H */ |
@ -0,0 +1,444 @@ |
|||||||
|
/*
|
||||||
|
* Copyright © 2012 Collabora, Ltd. |
||||||
|
* |
||||||
|
* Permission to use, copy, modify, distribute, and sell this software and |
||||||
|
* its documentation for any purpose is hereby granted without fee, provided |
||||||
|
* that the above copyright notice appear in all copies and that both that |
||||||
|
* copyright notice and this permission notice appear in supporting |
||||||
|
* documentation, and that the name of the copyright holders not be used in |
||||||
|
* advertising or publicity pertaining to distribution of the software |
||||||
|
* without specific, written prior permission. The copyright holders make |
||||||
|
* no representations about the suitability of this software for any |
||||||
|
* purpose. It is provided "as is" without express or implied warranty. |
||||||
|
* |
||||||
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS |
||||||
|
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND |
||||||
|
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY |
||||||
|
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER |
||||||
|
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF |
||||||
|
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
||||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <stdlib.h> |
||||||
|
#include <stdio.h> |
||||||
|
#include <string.h> |
||||||
|
#include <math.h> |
||||||
|
|
||||||
|
#include <EGL/egl.h> |
||||||
|
#include <GLES2/gl2.h> |
||||||
|
|
||||||
|
#include "compositor.h" |
||||||
|
#include "android-framebuffer.h" |
||||||
|
|
||||||
|
struct android_compositor; |
||||||
|
|
||||||
|
struct android_output { |
||||||
|
struct android_compositor *compositor; |
||||||
|
struct weston_output base; |
||||||
|
|
||||||
|
struct weston_mode mode; |
||||||
|
struct android_framebuffer *fb; |
||||||
|
EGLSurface egl_surface; |
||||||
|
}; |
||||||
|
|
||||||
|
struct android_seat { |
||||||
|
struct weston_seat base; |
||||||
|
}; |
||||||
|
|
||||||
|
struct android_compositor { |
||||||
|
struct weston_compositor base; |
||||||
|
|
||||||
|
struct android_seat *seat; |
||||||
|
}; |
||||||
|
|
||||||
|
static inline struct android_output * |
||||||
|
to_android_output(struct weston_output *base) |
||||||
|
{ |
||||||
|
return container_of(base, struct android_output, base); |
||||||
|
} |
||||||
|
|
||||||
|
static inline struct android_compositor * |
||||||
|
to_android_compositor(struct weston_compositor *base) |
||||||
|
{ |
||||||
|
return container_of(base, struct android_compositor, base); |
||||||
|
} |
||||||
|
|
||||||
|
static const char * |
||||||
|
egl_error_string(EGLint code) |
||||||
|
{ |
||||||
|
#define MYERRCODE(x) case x: return #x; |
||||||
|
switch (code) { |
||||||
|
MYERRCODE(EGL_SUCCESS) |
||||||
|
MYERRCODE(EGL_NOT_INITIALIZED) |
||||||
|
MYERRCODE(EGL_BAD_ACCESS) |
||||||
|
MYERRCODE(EGL_BAD_ALLOC) |
||||||
|
MYERRCODE(EGL_BAD_ATTRIBUTE) |
||||||
|
MYERRCODE(EGL_BAD_CONTEXT) |
||||||
|
MYERRCODE(EGL_BAD_CONFIG) |
||||||
|
MYERRCODE(EGL_BAD_CURRENT_SURFACE) |
||||||
|
MYERRCODE(EGL_BAD_DISPLAY) |
||||||
|
MYERRCODE(EGL_BAD_SURFACE) |
||||||
|
MYERRCODE(EGL_BAD_MATCH) |
||||||
|
MYERRCODE(EGL_BAD_PARAMETER) |
||||||
|
MYERRCODE(EGL_BAD_NATIVE_PIXMAP) |
||||||
|
MYERRCODE(EGL_BAD_NATIVE_WINDOW) |
||||||
|
MYERRCODE(EGL_CONTEXT_LOST) |
||||||
|
default: |
||||||
|
return "unknown"; |
||||||
|
} |
||||||
|
#undef MYERRCODE |
||||||
|
} |
||||||
|
|
||||||
|
static void |
||||||
|
print_egl_error_state(void) |
||||||
|
{ |
||||||
|
EGLint code; |
||||||
|
|
||||||
|
code = eglGetError(); |
||||||
|
fprintf(stderr, "EGL error state: %s (0x%04lx)\n", |
||||||
|
egl_error_string(code), (long)code); |
||||||
|
} |
||||||
|
|
||||||
|
static int |
||||||
|
android_output_make_current(struct android_output *output) |
||||||
|
{ |
||||||
|
struct android_compositor *compositor = output->compositor; |
||||||
|
EGLBoolean ret; |
||||||
|
static int errored; |
||||||
|
|
||||||
|
ret = eglMakeCurrent(compositor->base.display, output->egl_surface, |
||||||
|
output->egl_surface, compositor->base.context); |
||||||
|
if (ret == EGL_FALSE) { |
||||||
|
if (errored) |
||||||
|
return -1; |
||||||
|
errored = 1; |
||||||
|
fprintf(stderr, "Failed to make EGL context current.\n"); |
||||||
|
print_egl_error_state(); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
static void |
||||||
|
android_finish_frame(void *data) |
||||||
|
{ |
||||||
|
struct android_output *output = data; |
||||||
|
|
||||||
|
weston_output_finish_frame(&output->base, |
||||||
|
weston_compositor_get_time()); |
||||||
|
} |
||||||
|
|
||||||
|
static void |
||||||
|
android_output_repaint(struct weston_output *base, pixman_region32_t *damage) |
||||||
|
{ |
||||||
|
struct android_output *output = to_android_output(base); |
||||||
|
struct android_compositor *compositor = output->compositor; |
||||||
|
struct weston_surface *surface; |
||||||
|
struct wl_event_loop *loop; |
||||||
|
EGLBoolean ret; |
||||||
|
static int errored; |
||||||
|
|
||||||
|
if (android_output_make_current(output) < 0) |
||||||
|
return; |
||||||
|
|
||||||
|
wl_list_for_each_reverse(surface, &compositor->base.surface_list, link) |
||||||
|
weston_surface_draw(surface, &output->base, damage); |
||||||
|
|
||||||
|
weston_output_do_read_pixels(&output->base); |
||||||
|
|
||||||
|
ret = eglSwapBuffers(compositor->base.display, output->egl_surface); |
||||||
|
if (ret == EGL_FALSE && !errored) { |
||||||
|
errored = 1; |
||||||
|
fprintf(stderr, "Failed in eglSwapBuffers.\n"); |
||||||
|
print_egl_error_state(); |
||||||
|
} |
||||||
|
|
||||||
|
/* FIXME: does Android have a way to signal page flip done? */ |
||||||
|
loop = wl_display_get_event_loop(compositor->base.wl_display); |
||||||
|
wl_event_loop_add_idle(loop, android_finish_frame, output); |
||||||
|
} |
||||||
|
|
||||||
|
static void |
||||||
|
android_output_destroy(struct weston_output *base) |
||||||
|
{ |
||||||
|
struct android_output *output = to_android_output(base); |
||||||
|
|
||||||
|
wl_list_remove(&output->base.link); |
||||||
|
weston_output_destroy(&output->base); |
||||||
|
|
||||||
|
android_framebuffer_destroy(output->fb); |
||||||
|
|
||||||
|
free(output); |
||||||
|
} |
||||||
|
|
||||||
|
static struct android_output * |
||||||
|
android_output_create(struct android_compositor *compositor) |
||||||
|
{ |
||||||
|
struct android_output *output; |
||||||
|
|
||||||
|
output = calloc(1, sizeof *output); |
||||||
|
if (!output) |
||||||
|
return NULL; |
||||||
|
|
||||||
|
output->fb = android_framebuffer_create(); |
||||||
|
if (!output->fb) { |
||||||
|
free(output); |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
output->compositor = compositor; |
||||||
|
return output; |
||||||
|
} |
||||||
|
|
||||||
|
static void |
||||||
|
android_compositor_add_output(struct android_compositor *compositor, |
||||||
|
struct android_output *output) |
||||||
|
{ |
||||||
|
float mm_width, mm_height; |
||||||
|
|
||||||
|
output->base.repaint = android_output_repaint; |
||||||
|
output->base.destroy = android_output_destroy; |
||||||
|
output->base.assign_planes = NULL; |
||||||
|
output->base.set_backlight = NULL; |
||||||
|
output->base.set_dpms = NULL; |
||||||
|
output->base.switch_mode = NULL; |
||||||
|
|
||||||
|
/* only one static mode in list */ |
||||||
|
output->mode.flags = |
||||||
|
WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED; |
||||||
|
output->mode.width = output->fb->width; |
||||||
|
output->mode.height = output->fb->height; |
||||||
|
output->mode.refresh = ceilf(1000.0f * output->fb->refresh_rate); |
||||||
|
wl_list_init(&output->base.mode_list); |
||||||
|
wl_list_insert(&output->base.mode_list, &output->mode.link); |
||||||
|
|
||||||
|
output->base.current = &output->mode; |
||||||
|
output->base.origin = &output->mode; |
||||||
|
output->base.subpixel = WL_OUTPUT_SUBPIXEL_UNKNOWN; |
||||||
|
output->base.make = "unknown"; |
||||||
|
output->base.model = "unknown"; |
||||||
|
|
||||||
|
mm_width = output->fb->width / output->fb->xdpi * 25.4f; |
||||||
|
mm_height = output->fb->height / output->fb->ydpi * 25.4f; |
||||||
|
weston_output_init(&output->base, &compositor->base, |
||||||
|
0, 0, round(mm_width), round(mm_height), |
||||||
|
WL_OUTPUT_FLIPPED); |
||||||
|
wl_list_insert(compositor->base.output_list.prev, &output->base.link); |
||||||
|
} |
||||||
|
|
||||||
|
static void |
||||||
|
android_seat_destroy(struct android_seat *seat) |
||||||
|
{ |
||||||
|
weston_seat_release(&seat->base); |
||||||
|
free(seat); |
||||||
|
} |
||||||
|
|
||||||
|
static struct android_seat * |
||||||
|
android_seat_create(struct android_compositor *compositor) |
||||||
|
{ |
||||||
|
struct android_seat *seat; |
||||||
|
|
||||||
|
seat = calloc(1, sizeof *seat); |
||||||
|
if (!seat) |
||||||
|
return NULL; |
||||||
|
|
||||||
|
weston_seat_init(&seat->base, &compositor->base); |
||||||
|
compositor->base.seat = &seat->base; |
||||||
|
|
||||||
|
return seat; |
||||||
|
} |
||||||
|
|
||||||
|
static int |
||||||
|
android_egl_choose_config(struct android_compositor *compositor, |
||||||
|
struct android_framebuffer *fb, |
||||||
|
const EGLint *attribs) |
||||||
|
{ |
||||||
|
EGLBoolean ret; |
||||||
|
EGLint count = 0; |
||||||
|
EGLint matched = 0; |
||||||
|
EGLConfig *configs; |
||||||
|
int i; |
||||||
|
|
||||||
|
/*
|
||||||
|
* The logic is copied from Android frameworks/base/services/ |
||||||
|
* surfaceflinger/DisplayHardware/DisplayHardware.cpp |
||||||
|
*/ |
||||||
|
|
||||||
|
compositor->base.config = NULL; |
||||||
|
|
||||||
|
ret = eglGetConfigs(compositor->base.display, NULL, 0, &count); |
||||||
|
if (ret == EGL_FALSE || count < 1) |
||||||
|
return -1; |
||||||
|
|
||||||
|
configs = calloc(count, sizeof *configs); |
||||||
|
if (!configs) |
||||||
|
return -1; |
||||||
|
|
||||||
|
ret = eglChooseConfig(compositor->base.display, attribs, configs, |
||||||
|
count, &matched); |
||||||
|
if (ret == EGL_FALSE || matched < 1) |
||||||
|
goto out; |
||||||
|
|
||||||
|
for (i = 0; i < matched; ++i) { |
||||||
|
EGLint id; |
||||||
|
ret = eglGetConfigAttrib(compositor->base.display, configs[i], |
||||||
|
EGL_NATIVE_VISUAL_ID, &id); |
||||||
|
if (ret == EGL_FALSE) |
||||||
|
continue; |
||||||
|
if (id > 0 && fb->format == id) { |
||||||
|
compositor->base.config = configs[i]; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
out: |
||||||
|
free(configs); |
||||||
|
if (!compositor->base.config) |
||||||
|
return -1; |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
static int |
||||||
|
android_init_egl(struct android_compositor *compositor, |
||||||
|
struct android_output *output) |
||||||
|
{ |
||||||
|
EGLint eglmajor, eglminor; |
||||||
|
int ret; |
||||||
|
|
||||||
|
static const EGLint context_attrs[] = { |
||||||
|
EGL_CONTEXT_CLIENT_VERSION, 2, |
||||||
|
EGL_NONE |
||||||
|
}; |
||||||
|
|
||||||
|
static const EGLint config_attrs[] = { |
||||||
|
EGL_SURFACE_TYPE, EGL_WINDOW_BIT, |
||||||
|
EGL_RED_SIZE, 1, |
||||||
|
EGL_GREEN_SIZE, 1, |
||||||
|
EGL_BLUE_SIZE, 1, |
||||||
|
EGL_ALPHA_SIZE, 0, |
||||||
|
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, |
||||||
|
EGL_NONE |
||||||
|
}; |
||||||
|
|
||||||
|
compositor->base.display = eglGetDisplay(EGL_DEFAULT_DISPLAY); |
||||||
|
if (compositor->base.display == EGL_NO_DISPLAY) { |
||||||
|
fprintf(stderr, "Failed to create EGL display.\n"); |
||||||
|
print_egl_error_state(); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
ret = eglInitialize(compositor->base.display, &eglmajor, &eglminor); |
||||||
|
if (!ret) { |
||||||
|
fprintf(stderr, "Failed to initialise EGL.\n"); |
||||||
|
print_egl_error_state(); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
if (!eglBindAPI(EGL_OPENGL_ES_API)) { |
||||||
|
fprintf(stderr, "Failed to bind EGL_OPENGL_ES_API.\n"); |
||||||
|
print_egl_error_state(); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
ret = android_egl_choose_config(compositor, output->fb, config_attrs); |
||||||
|
if (ret < 0) { |
||||||
|
fprintf(stderr, "Failed to find an EGL config.\n"); |
||||||
|
print_egl_error_state(); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
compositor->base.context = eglCreateContext(compositor->base.display, |
||||||
|
compositor->base.config, |
||||||
|
EGL_NO_CONTEXT, |
||||||
|
context_attrs); |
||||||
|
if (compositor->base.context == EGL_NO_CONTEXT) { |
||||||
|
fprintf(stderr, "Failed to create a GL ES 2 context.\n"); |
||||||
|
print_egl_error_state(); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
output->egl_surface = eglCreateWindowSurface(compositor->base.display, |
||||||
|
compositor->base.config, |
||||||
|
output->fb->native_window, |
||||||
|
NULL); |
||||||
|
if (output->egl_surface == EGL_NO_SURFACE) { |
||||||
|
fprintf(stderr, "Failed to create FB EGLSurface.\n"); |
||||||
|
print_egl_error_state(); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
if (android_output_make_current(output) < 0) |
||||||
|
return -1; |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
static void |
||||||
|
android_fini_egl(struct android_compositor *compositor) |
||||||
|
{ |
||||||
|
eglMakeCurrent(compositor->base.display, |
||||||
|
EGL_NO_SURFACE, EGL_NO_SURFACE, |
||||||
|
EGL_NO_CONTEXT); |
||||||
|
|
||||||
|
eglTerminate(compositor->base.display); |
||||||
|
eglReleaseThread(); |
||||||
|
} |
||||||
|
|
||||||
|
static void |
||||||
|
android_compositor_destroy(struct weston_compositor *base) |
||||||
|
{ |
||||||
|
struct android_compositor *compositor = to_android_compositor(base); |
||||||
|
|
||||||
|
android_seat_destroy(compositor->seat); |
||||||
|
|
||||||
|
/* destroys outputs, too */ |
||||||
|
weston_compositor_shutdown(&compositor->base); |
||||||
|
|
||||||
|
android_fini_egl(compositor); |
||||||
|
|
||||||
|
free(compositor); |
||||||
|
} |
||||||
|
|
||||||
|
static struct weston_compositor * |
||||||
|
android_compositor_create(struct wl_display *display) |
||||||
|
{ |
||||||
|
struct android_compositor *compositor; |
||||||
|
struct android_output *output; |
||||||
|
|
||||||
|
compositor = calloc(1, sizeof *compositor); |
||||||
|
if (compositor == NULL) |
||||||
|
return NULL; |
||||||
|
|
||||||
|
compositor->base.destroy = android_compositor_destroy; |
||||||
|
|
||||||
|
compositor->base.focus = 1; |
||||||
|
|
||||||
|
/* FIXME: all cleanup on failure is missing */ |
||||||
|
|
||||||
|
output = android_output_create(compositor); |
||||||
|
if (!output) |
||||||
|
return NULL; |
||||||
|
|
||||||
|
if (android_init_egl(compositor, output) < 0) |
||||||
|
return NULL; |
||||||
|
|
||||||
|
if (weston_compositor_init(&compositor->base, display) < 0) |
||||||
|
return NULL; |
||||||
|
|
||||||
|
android_compositor_add_output(compositor, output); |
||||||
|
|
||||||
|
compositor->seat = android_seat_create(compositor); |
||||||
|
if (!compositor->seat) |
||||||
|
return NULL; |
||||||
|
|
||||||
|
return &compositor->base; |
||||||
|
} |
||||||
|
|
||||||
|
WL_EXPORT struct weston_compositor * |
||||||
|
backend_init(struct wl_display *display, int argc, char *argv[]) |
||||||
|
{ |
||||||
|
return android_compositor_create(display); |
||||||
|
} |
Loading…
Reference in new issue