mirror of
https://github.com/vectras-team/termux-x11.git
synced 2024-11-23 06:41:02 +00:00
Fixing displaying on devices which do not support sampling from HAL_PIXEL_FORMAT_BGRA_8888
``` gles-renderer: renderer_set_buffer0 ANGLE Info:Debug.cpp:490 (insertMessage): EGL ERROR: eglCreateImageKHR: Sampling from AHardwareBuffer externalFormat 0x5 is unsupported gles-renderer: Xlorie: egl error on line 264: Invalid argument gles-renderer: Binding AHardwareBuffer to an EGLImage failed. ```
This commit is contained in:
parent
4acf4b2422
commit
84901c2f1c
@ -103,6 +103,7 @@ typedef struct {
|
|||||||
AHardwareBuffer* buffer;
|
AHardwareBuffer* buffer;
|
||||||
Bool locked;
|
Bool locked;
|
||||||
Bool legacyDrawing;
|
Bool legacyDrawing;
|
||||||
|
uint8_t flip;
|
||||||
uint32_t width, height;
|
uint32_t width, height;
|
||||||
} root;
|
} root;
|
||||||
} lorieScreenInfo, *lorieScreenInfoPtr;
|
} lorieScreenInfo, *lorieScreenInfoPtr;
|
||||||
@ -323,7 +324,9 @@ static void lorieUpdateBuffer(void) {
|
|||||||
d0.height = pScreenPtr->height;
|
d0.height = pScreenPtr->height;
|
||||||
d0.layers = 1;
|
d0.layers = 1;
|
||||||
d0.usage = USAGE;
|
d0.usage = USAGE;
|
||||||
d0.format = 5; // Stands to HAL_PIXEL_FORMAT_BGRA_8888
|
d0.format = pvfb->root.flip
|
||||||
|
? AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM
|
||||||
|
: AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM;
|
||||||
|
|
||||||
/* I could use this, but in this case I must swap colours in the shader. */
|
/* I could use this, but in this case I must swap colours in the shader. */
|
||||||
// desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM;
|
// desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM;
|
||||||
@ -418,11 +421,11 @@ static void lorieTimerCallback(int fd, unused int r, void *arg) {
|
|||||||
ScreenPtr pScreen = (ScreenPtr) arg;
|
ScreenPtr pScreen = (ScreenPtr) arg;
|
||||||
|
|
||||||
loriePixmapUnlock(pScreen->GetScreenPixmap(pScreen));
|
loriePixmapUnlock(pScreen->GetScreenPixmap(pScreen));
|
||||||
redrawn = renderer_redraw();
|
redrawn = renderer_redraw(pvfb->root.flip);
|
||||||
if (loriePixmapLock(pScreen->GetScreenPixmap(pScreen)) && redrawn)
|
if (loriePixmapLock(pScreen->GetScreenPixmap(pScreen)) && redrawn)
|
||||||
DamageEmpty(pvfb->damage);
|
DamageEmpty(pvfb->damage);
|
||||||
} else if (pvfb->cursorMoved)
|
} else if (pvfb->cursorMoved)
|
||||||
renderer_redraw();
|
renderer_redraw(pvfb->root.flip);
|
||||||
|
|
||||||
pvfb->cursorMoved = FALSE;
|
pvfb->cursorMoved = FALSE;
|
||||||
}
|
}
|
||||||
@ -662,7 +665,7 @@ Bool lorieChangeWindow(unused ClientPtr pClient, void *closure) {
|
|||||||
|
|
||||||
if (pvfb->root.legacyDrawing) {
|
if (pvfb->root.legacyDrawing) {
|
||||||
renderer_update_root(pScreenPtr->width, pScreenPtr->height, ((PixmapPtr) pScreenPtr->devPrivate)->devPrivate.ptr);
|
renderer_update_root(pScreenPtr->width, pScreenPtr->height, ((PixmapPtr) pScreenPtr->devPrivate)->devPrivate.ptr);
|
||||||
renderer_redraw();
|
renderer_redraw(pvfb->root.flip);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -714,7 +717,7 @@ InitOutput(ScreenInfo * screen_info, int argc, char **argv) {
|
|||||||
screen_info->bitmapBitOrder = BITMAP_BIT_ORDER;
|
screen_info->bitmapBitOrder = BITMAP_BIT_ORDER;
|
||||||
screen_info->numPixmapFormats = ARRAY_SIZE(depths);
|
screen_info->numPixmapFormats = ARRAY_SIZE(depths);
|
||||||
|
|
||||||
renderer_init();
|
renderer_init(&pvfb->root.legacyDrawing, &pvfb->root.flip);
|
||||||
xorgGlxCreateVendor();
|
xorgGlxCreateVendor();
|
||||||
lorieInitSelectionCallback();
|
lorieInitSelectionCallback();
|
||||||
|
|
||||||
|
@ -112,13 +112,17 @@ static const char vertex_shader[] =
|
|||||||
" outTexCoords = texCoords;\n"
|
" outTexCoords = texCoords;\n"
|
||||||
" gl_Position = position;\n"
|
" gl_Position = position;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
static const char fragment_shader[] =
|
|
||||||
"precision mediump float;\n"
|
#define FRAGMENT_SHADER(texture) \
|
||||||
"varying vec2 outTexCoords;\n"
|
"precision mediump float;\n" \
|
||||||
"uniform sampler2D texture;\n"
|
"varying vec2 outTexCoords;\n" \
|
||||||
"void main(void) {\n"
|
"uniform sampler2D texture;\n" \
|
||||||
" gl_FragColor = texture2D(texture, outTexCoords);\n"
|
"void main(void) {\n" \
|
||||||
"}\n";
|
" gl_FragColor = texture2D(texture, outTexCoords)" texture ";\n" \
|
||||||
|
"}\n"
|
||||||
|
|
||||||
|
static const char fragment_shader[] = FRAGMENT_SHADER();
|
||||||
|
static const char fragment_shader_bgra[] = FRAGMENT_SHADER(".bgra");
|
||||||
|
|
||||||
static EGLDisplay egl_display = EGL_NO_DISPLAY;
|
static EGLDisplay egl_display = EGL_NO_DISPLAY;
|
||||||
static EGLContext ctx = EGL_NO_CONTEXT;
|
static EGLContext ctx = EGL_NO_CONTEXT;
|
||||||
@ -139,8 +143,9 @@ static struct {
|
|||||||
} cursor;
|
} cursor;
|
||||||
|
|
||||||
GLuint g_texture_program = 0, gv_pos = 0, gv_coords = 0;
|
GLuint g_texture_program = 0, gv_pos = 0, gv_coords = 0;
|
||||||
|
GLuint g_texture_program_bgra = 0, gv_pos_bgra = 0, gv_coords_bgra = 0;
|
||||||
|
|
||||||
int renderer_init(void) {
|
int renderer_init(int* legacy_drawing, uint8_t* flip) {
|
||||||
EGLint major, minor;
|
EGLint major, minor;
|
||||||
EGLint numConfigs;
|
EGLint numConfigs;
|
||||||
const EGLint configAttribs[] = {
|
const EGLint configAttribs[] = {
|
||||||
@ -208,6 +213,49 @@ int renderer_init(void) {
|
|||||||
}
|
}
|
||||||
eglCheckError(__LINE__);
|
eglCheckError(__LINE__);
|
||||||
|
|
||||||
|
{
|
||||||
|
// Some devices do not support sampling from HAL_PIXEL_FORMAT_BGRA_8888, here we are checking it.
|
||||||
|
const EGLint imageAttributes[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
|
||||||
|
EGLClientBuffer clientBuffer;
|
||||||
|
AHardwareBuffer *new = NULL;
|
||||||
|
int status;
|
||||||
|
AHardwareBuffer_Desc d0 = {
|
||||||
|
.width = 64,
|
||||||
|
.height = 64,
|
||||||
|
.layers = 1,
|
||||||
|
.usage = AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN | AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN,
|
||||||
|
.format = AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM
|
||||||
|
};
|
||||||
|
|
||||||
|
status = AHardwareBuffer_allocate(&d0, &new);
|
||||||
|
if (status != 0 || new == NULL) {
|
||||||
|
loge("Failed to allocate native buffer (%p, error %d)", new, status);
|
||||||
|
loge("Forcing legacy drawing");
|
||||||
|
*legacy_drawing = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
clientBuffer = eglGetNativeClientBufferANDROID(new);
|
||||||
|
if (!clientBuffer) {
|
||||||
|
eglCheckError(__LINE__);
|
||||||
|
loge("Failed to obtain EGLClientBuffer from AHardwareBuffer");
|
||||||
|
loge("Forcing legacy drawing");
|
||||||
|
*legacy_drawing = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!eglCreateImageKHR(egl_display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, clientBuffer, imageAttributes)) {
|
||||||
|
if (eglGetError() == EGL_BAD_PARAMETER) {
|
||||||
|
loge("Sampling from HAL_PIXEL_FORMAT_BGRA_8888 is not supported, forcing AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM");
|
||||||
|
*flip = 1;
|
||||||
|
} else {
|
||||||
|
loge("Failed to obtain EGLImageKHR from EGLClientBuffer");
|
||||||
|
loge("Forcing legacy drawing");
|
||||||
|
*legacy_drawing = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,6 +278,7 @@ void renderer_set_buffer(AHardwareBuffer* buf) {
|
|||||||
const EGLint imageAttributes[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
|
const EGLint imageAttributes[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
|
||||||
EGLClientBuffer clientBuffer;
|
EGLClientBuffer clientBuffer;
|
||||||
AHardwareBuffer_Desc desc = {0};
|
AHardwareBuffer_Desc desc = {0};
|
||||||
|
uint8_t flip = 0;
|
||||||
|
|
||||||
if (eglGetCurrentContext() == EGL_NO_CONTEXT) {
|
if (eglGetCurrentContext() == EGL_NO_CONTEXT) {
|
||||||
loge("There is no current context, `renderer_set_buffer` call is cancelled");
|
loge("There is no current context, `renderer_set_buffer` call is cancelled");
|
||||||
@ -258,11 +307,14 @@ void renderer_set_buffer(AHardwareBuffer* buf) {
|
|||||||
loge("Failed to obtain EGLClientBuffer from AHardwareBuffer");
|
loge("Failed to obtain EGLClientBuffer from AHardwareBuffer");
|
||||||
}
|
}
|
||||||
image = clientBuffer ? eglCreateImageKHR(egl_display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, clientBuffer, imageAttributes) : NULL;
|
image = clientBuffer ? eglCreateImageKHR(egl_display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, clientBuffer, imageAttributes) : NULL;
|
||||||
if (image != NULL)
|
if (image != NULL) {
|
||||||
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
|
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
|
||||||
else {
|
flip = desc.format != AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM;
|
||||||
eglCheckError(__LINE__);
|
} else {
|
||||||
loge("Binding AHardwareBuffer to an EGLImage failed.");
|
if (clientBuffer) {
|
||||||
|
eglCheckError(__LINE__);
|
||||||
|
loge("Binding AHardwareBuffer to an EGLImage failed.");
|
||||||
|
}
|
||||||
|
|
||||||
display.width = 1;
|
display.width = 1;
|
||||||
display.height = 1;
|
display.height = 1;
|
||||||
@ -279,7 +331,7 @@ void renderer_set_buffer(AHardwareBuffer* buf) {
|
|||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data); checkGlError();
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data); checkGlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer_redraw();
|
renderer_redraw(flip);
|
||||||
|
|
||||||
log("renderer_set_buffer %p %d %d", buffer, desc.width, desc.height);
|
log("renderer_set_buffer %p %d %d", buffer, desc.width, desc.height);
|
||||||
}
|
}
|
||||||
@ -331,9 +383,19 @@ void renderer_set_window(EGLNativeWindowType window, AHardwareBuffer* new_buffer
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_texture_program_bgra = create_program(vertex_shader, fragment_shader_bgra);
|
||||||
|
if (!g_texture_program_bgra) {
|
||||||
|
log("Xlorie: GLESv2: Unable to create bgra shader program.\n");
|
||||||
|
eglCheckError(__LINE__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
gv_pos = (GLuint) glGetAttribLocation(g_texture_program, "position"); checkGlError();
|
gv_pos = (GLuint) glGetAttribLocation(g_texture_program, "position"); checkGlError();
|
||||||
gv_coords = (GLuint) glGetAttribLocation(g_texture_program, "texCoords"); checkGlError();
|
gv_coords = (GLuint) glGetAttribLocation(g_texture_program, "texCoords"); checkGlError();
|
||||||
|
|
||||||
|
gv_pos_bgra = (GLuint) glGetAttribLocation(g_texture_program_bgra, "position"); checkGlError();
|
||||||
|
gv_coords_bgra = (GLuint) glGetAttribLocation(g_texture_program_bgra, "texCoords"); checkGlError();
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0); checkGlError();
|
glActiveTexture(GL_TEXTURE0); checkGlError();
|
||||||
glGenTextures(1, &display.id); checkGlError();
|
glGenTextures(1, &display.id); checkGlError();
|
||||||
glGenTextures(1, &cursor.id); checkGlError();
|
glGenTextures(1, &cursor.id); checkGlError();
|
||||||
@ -398,7 +460,7 @@ void renderer_set_cursor_coordinates(int x, int y) {
|
|||||||
cursor.y = (float) y;
|
cursor.y = (float) y;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw(GLuint id, float x0, float y0, float x1, float y1);
|
static void draw(GLuint id, float x0, float y0, float x1, float y1, uint8_t flip);
|
||||||
static void draw_cursor(void);
|
static void draw_cursor(void);
|
||||||
|
|
||||||
float ia = 0;
|
float ia = 0;
|
||||||
@ -407,13 +469,13 @@ int renderer_should_redraw(void) {
|
|||||||
return sfc != EGL_NO_SURFACE && eglGetCurrentContext() != EGL_NO_CONTEXT;
|
return sfc != EGL_NO_SURFACE && eglGetCurrentContext() != EGL_NO_CONTEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
int renderer_redraw(void) {
|
int renderer_redraw(uint8_t flip) {
|
||||||
int err = EGL_SUCCESS;
|
int err = EGL_SUCCESS;
|
||||||
|
|
||||||
if (!sfc || eglGetCurrentContext() == EGL_NO_CONTEXT)
|
if (!sfc || eglGetCurrentContext() == EGL_NO_CONTEXT)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
draw(display.id, -1.f, -1.f, 1.f, 1.f);
|
draw(display.id, -1.f, -1.f, 1.f, 1.f, flip);
|
||||||
draw_cursor();
|
draw_cursor();
|
||||||
if (eglSwapBuffers(egl_display, sfc) != EGL_TRUE) {
|
if (eglSwapBuffers(egl_display, sfc) != EGL_TRUE) {
|
||||||
err = eglGetError();
|
err = eglGetError();
|
||||||
@ -496,7 +558,7 @@ static GLuint create_program(const char* p_vertex_source, const char* p_fragment
|
|||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw(GLuint id, float x0, float y0, float x1, float y1) {
|
static void draw(GLuint id, float x0, float y0, float x1, float y1, uint8_t flip) {
|
||||||
float coords[20] = {
|
float coords[20] = {
|
||||||
x0, -y0, 0.f, 0.f, 0.f,
|
x0, -y0, 0.f, 0.f, 0.f,
|
||||||
x1, -y0, 0.f, 1.f, 0.f,
|
x1, -y0, 0.f, 1.f, 0.f,
|
||||||
@ -504,14 +566,16 @@ static void draw(GLuint id, float x0, float y0, float x1, float y1) {
|
|||||||
x1, -y1, 0.f, 1.f, 1.f,
|
x1, -y1, 0.f, 1.f, 1.f,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
GLuint p = flip ? gv_pos_bgra : gv_pos, c = flip ? gv_coords_bgra : gv_coords;
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0); checkGlError();
|
glActiveTexture(GL_TEXTURE0); checkGlError();
|
||||||
glUseProgram(g_texture_program); checkGlError();
|
glUseProgram(flip ? g_texture_program_bgra : g_texture_program); checkGlError();
|
||||||
glBindTexture(GL_TEXTURE_2D, id); checkGlError();
|
glBindTexture(GL_TEXTURE_2D, id); checkGlError();
|
||||||
|
|
||||||
glVertexAttribPointer(gv_pos, 3, GL_FLOAT, GL_FALSE, 20, coords); checkGlError();
|
glVertexAttribPointer(p, 3, GL_FLOAT, GL_FALSE, 20, coords); checkGlError();
|
||||||
glVertexAttribPointer(gv_coords, 2, GL_FLOAT, GL_FALSE, 20, &coords[3]); checkGlError();
|
glVertexAttribPointer(c, 2, GL_FLOAT, GL_FALSE, 20, &coords[3]); checkGlError();
|
||||||
glEnableVertexAttribArray(gv_pos); checkGlError();
|
glEnableVertexAttribArray(p); checkGlError();
|
||||||
glEnableVertexAttribArray(gv_coords); checkGlError();
|
glEnableVertexAttribArray(c); checkGlError();
|
||||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); checkGlError();
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); checkGlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -527,7 +591,7 @@ maybe_unused static void draw_cursor(void) {
|
|||||||
h = 2.f * cursor.height / display.height;
|
h = 2.f * cursor.height / display.height;
|
||||||
glEnable(GL_BLEND); checkGlError();
|
glEnable(GL_BLEND); checkGlError();
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); checkGlError();
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); checkGlError();
|
||||||
draw(cursor.id, x, y, x + w, y + h);
|
draw(cursor.id, x, y, x + w, y + h, false);
|
||||||
glDisable(GL_BLEND); checkGlError();
|
glDisable(GL_BLEND); checkGlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,13 +12,15 @@
|
|||||||
typedef void (*renderer_message_func_type) (int type, int verb, const char *format, ...);
|
typedef void (*renderer_message_func_type) (int type, int verb, const char *format, ...);
|
||||||
maybe_unused void renderer_message_func(renderer_message_func_type function);
|
maybe_unused void renderer_message_func(renderer_message_func_type function);
|
||||||
|
|
||||||
maybe_unused int renderer_init(void);
|
maybe_unused int renderer_init(int* legacy_drawing, uint8_t* flip);
|
||||||
maybe_unused void renderer_set_buffer(AHardwareBuffer* buffer);
|
maybe_unused void renderer_set_buffer(AHardwareBuffer* buffer);
|
||||||
maybe_unused void renderer_set_window(struct ANativeWindow* native_window, AHardwareBuffer* buffer);
|
maybe_unused void renderer_set_window(struct ANativeWindow* native_window, AHardwareBuffer* buffer);
|
||||||
maybe_unused int renderer_should_redraw(void);
|
maybe_unused int renderer_should_redraw(void);
|
||||||
maybe_unused int renderer_redraw(void);
|
maybe_unused int renderer_redraw(uint8_t flip);
|
||||||
maybe_unused void renderer_print_fps(float millis);
|
maybe_unused void renderer_print_fps(float millis);
|
||||||
|
|
||||||
maybe_unused void renderer_update_root(int w, int h, void* data);
|
maybe_unused void renderer_update_root(int w, int h, void* data);
|
||||||
maybe_unused void renderer_update_cursor(int w, int h, int xhot, int yhot, void* data);
|
maybe_unused void renderer_update_cursor(int w, int h, int xhot, int yhot, void* data);
|
||||||
maybe_unused void renderer_set_cursor_coordinates(int x, int y);
|
maybe_unused void renderer_set_cursor_coordinates(int x, int y);
|
||||||
|
|
||||||
|
#define AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM 5 // Stands to HAL_PIXEL_FORMAT_BGRA_8888
|
@ -463,7 +463,7 @@ public class MainActivity extends AppCompatActivity implements View.OnApplyWindo
|
|||||||
return;
|
return;
|
||||||
try {
|
try {
|
||||||
Log.v("LorieBroadcastReceiver", "Extracting X connection socket.");
|
Log.v("LorieBroadcastReceiver", "Extracting X connection socket.");
|
||||||
ParcelFileDescriptor fd = service.getXConnection();
|
ParcelFileDescriptor fd = service == null ? null : service.getXConnection();
|
||||||
if (fd != null) {
|
if (fd != null) {
|
||||||
LorieView.connect(fd.detachFd());
|
LorieView.connect(fd.detachFd());
|
||||||
getLorieView().triggerCallback();
|
getLorieView().triggerCallback();
|
||||||
|
Loading…
Reference in New Issue
Block a user