Skip to content

Commit

Permalink
Enable trilinear filtering for OpenGL
Browse files Browse the repository at this point in the history
Improve downscaling quality if mipmapping is available.

Suggested-by: Giumo Clanjor (哆啦比猫/兰威举) <[email protected]>

Fixes #40 <#40>
Ref: <#40 (comment)>
  • Loading branch information
rom1v committed Apr 13, 2020
1 parent 9f029da commit 08a175b
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 6 deletions.
1 change: 1 addition & 0 deletions app/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ src = [
'src/file_handler.c',
'src/fps_counter.c',
'src/input_manager.c',
'src/opengl.c',
'src/receiver.c',
'src/recorder.c',
'src/scrcpy.c',
Expand Down
56 changes: 56 additions & 0 deletions app/src/opengl.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include "opengl.h"

#include <assert.h>
#include <stdio.h>
#include "SDL2/SDL.h"

void
sc_opengl_init(struct sc_opengl *gl) {
gl->GetString = SDL_GL_GetProcAddress("glGetString");
assert(gl->GetString);

gl->TexParameterf = SDL_GL_GetProcAddress("glTexParameterf");
assert(gl->TexParameterf);

gl->TexParameteri = SDL_GL_GetProcAddress("glTexParameteri");
assert(gl->TexParameteri);

// optional
gl->GenerateMipmap = SDL_GL_GetProcAddress("glGenerateMipmap");

const char *version = (const char *) gl->GetString(GL_VERSION);
assert(version);
gl->version = version;

#define OPENGL_ES_PREFIX "OpenGL ES "
/* starts with "OpenGL ES " */
gl->is_opengles = !strncmp(gl->version, OPENGL_ES_PREFIX,
sizeof(OPENGL_ES_PREFIX) - 1);
if (gl->is_opengles) {
/* skip the prefix */
version += sizeof(PREFIX) - 1;
}

int r = sscanf(version, "%d.%d", &gl->version_major, &gl->version_minor);
if (r != 2) {
// failed to parse the version
gl->version_major = 0;
gl->version_minor = 0;
}
}

bool
sc_opengl_version_at_least(struct sc_opengl *gl,
int minver_major, int minver_minor,
int minver_es_major, int minver_es_minor)
{
if (gl->is_opengles) {
return gl->version_major > minver_es_major
|| (gl->version_major == minver_es_major
&& gl->version_minor >= minver_es_minor);
}

return gl->version_major > minver_major
|| (gl->version_major == minver_major
&& gl->version_minor >= minver_minor);
}
36 changes: 36 additions & 0 deletions app/src/opengl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#ifndef SC_OPENGL_H
#define SC_OPENGL_H

#include <stdbool.h>
#include <SDL2/SDL_opengl.h>

#include "config.h"

struct sc_opengl {
const char *version;
bool is_opengles;
int version_major;
int version_minor;

const GLubyte *
(*GetString)(GLenum name);

void
(*TexParameterf)(GLenum target, GLenum pname, GLfloat param);

void
(*TexParameteri)(GLenum target, GLenum pname, GLint param);

void
(*GenerateMipmap)(GLenum target);
};

void
sc_opengl_init(struct sc_opengl *gl);

bool
sc_opengl_version_at_least(struct sc_opengl *gl,
int minver_major, int minver_minor,
int minver_es_major, int minver_es_minor);

#endif
61 changes: 55 additions & 6 deletions app/src/screen.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,30 @@ screen_init(struct screen *screen) {
}

static inline SDL_Texture *
create_texture(SDL_Renderer *renderer, struct size frame_size) {
return SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12,
SDL_TEXTUREACCESS_STREAMING,
frame_size.width, frame_size.height);
create_texture(struct screen *screen) {
SDL_Renderer *renderer = screen->renderer;
struct size size = screen->frame_size;
SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12,
SDL_TEXTUREACCESS_STREAMING,
size.width, size.height);
if (!texture) {
return NULL;
}

if (screen->mipmaps) {
struct sc_opengl *gl = &screen->gl;

SDL_GL_BindTexture(texture, NULL, NULL);

// Enable trilinear filtering for downscaling
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_LINEAR);
gl->TexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -.5f);

SDL_GL_UnbindTexture(texture);
}

return texture;
}

bool
Expand Down Expand Up @@ -238,6 +258,28 @@ screen_init_rendering(struct screen *screen, const char *window_title,
return false;
}

// stats with "opengl"
screen->use_opengl = renderer_name && !strncmp(renderer_name, "opengl", 6);
if (screen->use_opengl) {
struct sc_opengl *gl = &screen->gl;
sc_opengl_init(gl);

LOGI("OpenGL version: %s", gl->version);

bool supports_mipmaps =
sc_opengl_version_at_least(gl, 3, 0, /* OpenGL 3.0+ */
2, 0 /* OpenGL ES 2.0+ */);
if (supports_mipmaps) {
LOGI("Trilinear filtering enabled");
screen->mipmaps = true;
} else {
LOGW("Trilinear filtering disabled "
"(OpenGL 3.0+ or ES 2.0+ required)");
}
} else {
LOGW("Trilinear filtering disabled (not an OpenGL renderer)");
}

SDL_Surface *icon = read_xpm(icon_xpm);
if (icon) {
SDL_SetWindowIcon(screen->window, icon);
Expand All @@ -248,7 +290,7 @@ screen_init_rendering(struct screen *screen, const char *window_title,

LOGI("Initial texture: %" PRIu16 "x%" PRIu16, frame_size.width,
frame_size.height);
screen->texture = create_texture(screen->renderer, frame_size);
screen->texture = create_texture(screen);
if (!screen->texture) {
LOGC("Could not create texture: %s", SDL_GetError());
screen_destroy(screen);
Expand Down Expand Up @@ -346,7 +388,7 @@ prepare_for_frame(struct screen *screen, struct size new_frame_size) {

LOGI("New texture: %" PRIu16 "x%" PRIu16,
screen->frame_size.width, screen->frame_size.height);
screen->texture = create_texture(screen->renderer, new_frame_size);
screen->texture = create_texture(screen);
if (!screen->texture) {
LOGC("Could not create texture: %s", SDL_GetError());
return false;
Expand All @@ -363,6 +405,13 @@ update_texture(struct screen *screen, const AVFrame *frame) {
frame->data[0], frame->linesize[0],
frame->data[1], frame->linesize[1],
frame->data[2], frame->linesize[2]);

if (screen->mipmaps) {
assert(screen->use_opengl);
SDL_GL_BindTexture(screen->texture, NULL, NULL);
screen->gl.GenerateMipmap(GL_TEXTURE_2D);
SDL_GL_UnbindTexture(screen->texture);
}
}

bool
Expand Down
7 changes: 7 additions & 0 deletions app/src/screen.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "config.h"
#include "common.h"
#include "opengl.h"

#define WINDOW_POSITION_UNDEFINED (-0x8000)

Expand All @@ -16,6 +17,8 @@ struct screen {
SDL_Window *window;
SDL_Renderer *renderer;
SDL_Texture *texture;
bool use_opengl;
struct sc_opengl gl;
struct size frame_size;
struct size content_size; // rotated frame_size
// The window size the last time it was not maximized or fullscreen.
Expand All @@ -29,12 +32,15 @@ struct screen {
bool fullscreen;
bool maximized;
bool no_window;
bool mipmaps;
};

#define SCREEN_INITIALIZER { \
.window = NULL, \
.renderer = NULL, \
.texture = NULL, \
.use_opengl = false, \
.gl = {0}, \
.frame_size = { \
.width = 0, \
.height = 0, \
Expand All @@ -56,6 +62,7 @@ struct screen {
.fullscreen = false, \
.maximized = false, \
.no_window = false, \
.mipmaps = false, \
}

// initialize default values
Expand Down

0 comments on commit 08a175b

Please sign in to comment.