mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-19 21:08:07 +00:00
fix(core): create separate display buffer for gamma correction
So that the screenshots in UI tests are not affected by it. Also not doing the gamma correction in case of SDL_VIDEODRIVER=dummy. [no changelog]
This commit is contained in:
parent
4babb3f5db
commit
31ef923e15
@ -148,14 +148,20 @@ static int SDLCALL emulator_event_filter(void *userdata, SDL_Event *event) {
|
|||||||
case SDLK_p:
|
case SDLK_p:
|
||||||
display_save("emu");
|
display_save("emu");
|
||||||
return 0;
|
return 0;
|
||||||
|
#if defined TREZOR_MODEL_T
|
||||||
|
// Left and right arrows controlling display gamma
|
||||||
|
// Only for TT (in button models, arrows do different things)
|
||||||
case SDLK_LEFT:
|
case SDLK_LEFT:
|
||||||
DISPLAY_GAMMA = fmaxf(0.0f, DISPLAY_GAMMA - 0.05f);
|
DISPLAY_GAMMA = fmaxf(0.0f, DISPLAY_GAMMA - 0.05f);
|
||||||
printf("DISPLAY_GAMMA: %0.2f\n", DISPLAY_GAMMA);
|
printf("DISPLAY_GAMMA: %0.2f\n", DISPLAY_GAMMA);
|
||||||
|
display_refresh();
|
||||||
return 0;
|
return 0;
|
||||||
case SDLK_RIGHT:
|
case SDLK_RIGHT:
|
||||||
DISPLAY_GAMMA = fminf(8.0f, DISPLAY_GAMMA + 0.05f);
|
DISPLAY_GAMMA = fminf(8.0f, DISPLAY_GAMMA + 0.05f);
|
||||||
printf("DISPLAY_GAMMA: %0.2f\n", DISPLAY_GAMMA);
|
printf("DISPLAY_GAMMA: %0.2f\n", DISPLAY_GAMMA);
|
||||||
|
display_refresh();
|
||||||
return 0;
|
return 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,11 @@
|
|||||||
|
|
||||||
static SDL_Window *WINDOW;
|
static SDL_Window *WINDOW;
|
||||||
static SDL_Renderer *RENDERER;
|
static SDL_Renderer *RENDERER;
|
||||||
|
// BUFFER_TO_DISPLAY will contain the actual pixels to be displayed,
|
||||||
|
// it will be filled from BUFFER by gamma-correcting the pixel colors.
|
||||||
|
// Screenshots will be taken with data from BUFFER.
|
||||||
static SDL_Surface *BUFFER;
|
static SDL_Surface *BUFFER;
|
||||||
|
static SDL_Surface *BUFFER_TO_DISPLAY;
|
||||||
static SDL_Texture *TEXTURE, *BACKGROUND;
|
static SDL_Texture *TEXTURE, *BACKGROUND;
|
||||||
|
|
||||||
static SDL_Surface *PREV_SAVED;
|
static SDL_Surface *PREV_SAVED;
|
||||||
@ -71,9 +75,14 @@ static SDL_Surface *PREV_SAVED;
|
|||||||
static int DISPLAY_BACKLIGHT = -1;
|
static int DISPLAY_BACKLIGHT = -1;
|
||||||
static int DISPLAY_ORIENTATION = -1;
|
static int DISPLAY_ORIENTATION = -1;
|
||||||
float DISPLAY_GAMMA = 0.55f;
|
float DISPLAY_GAMMA = 0.55f;
|
||||||
|
// Will depend on SDL_VIDEODRIVER env variable
|
||||||
|
static bool DO_GAMMA_CORRECTION = true;
|
||||||
int sdl_display_res_x = DISPLAY_RESX, sdl_display_res_y = DISPLAY_RESY;
|
int sdl_display_res_x = DISPLAY_RESX, sdl_display_res_y = DISPLAY_RESY;
|
||||||
int sdl_touch_offset_x, sdl_touch_offset_y;
|
int sdl_touch_offset_x, sdl_touch_offset_y;
|
||||||
|
|
||||||
|
// Using RGB565 (16-bit) color format.
|
||||||
|
typedef uint16_t pixel_color;
|
||||||
|
|
||||||
// this is just for compatibility with DMA2D using algorithms
|
// this is just for compatibility with DMA2D using algorithms
|
||||||
uint8_t *const DISPLAY_DATA_ADDRESS = 0;
|
uint8_t *const DISPLAY_DATA_ADDRESS = 0;
|
||||||
|
|
||||||
@ -89,45 +98,46 @@ static struct {
|
|||||||
} pos;
|
} pos;
|
||||||
} PIXELWINDOW;
|
} PIXELWINDOW;
|
||||||
|
|
||||||
uint16_t gamma_correct(uint16_t c) {
|
pixel_color gamma_correct(pixel_color c) {
|
||||||
// NOTE: 0x1f/31 and 0x3f/63 are maximum values of RGB components
|
// NOTE: 0x1f/31 and 0x3f/63 are maximum values of RGB components
|
||||||
// given the color is 16-bit (5 bits for R, 6 bits for G, 5 bits for B).
|
// given the color is 16-bit (5 bits for R, 6 bits for G, 5 bits for B).
|
||||||
int r = (c >> 11) & 0x1f;
|
int r = (c >> 11) & 0x1f;
|
||||||
int g = (c >> 5) & 0x3f;
|
int g = (c >> 5) & 0x3f;
|
||||||
int b = c & 0x1f;
|
int b = c & 0x1f;
|
||||||
|
|
||||||
float fr = r / 31.0;
|
r = (int)round(pow(r / 31.0, DISPLAY_GAMMA) * 31.0);
|
||||||
float fg = g / 63.0;
|
g = (int)round(pow(g / 63.0, DISPLAY_GAMMA) * 63.0);
|
||||||
float fb = b / 31.0;
|
b = (int)round(pow(b / 31.0, DISPLAY_GAMMA) * 31.0);
|
||||||
|
|
||||||
fr = pow(fr, DISPLAY_GAMMA);
|
|
||||||
fg = pow(fg, DISPLAY_GAMMA);
|
|
||||||
fb = pow(fb, DISPLAY_GAMMA);
|
|
||||||
|
|
||||||
r = (int)round(fr * 31.0);
|
|
||||||
g = (int)round(fg * 63.0);
|
|
||||||
b = (int)round(fb * 31.0);
|
|
||||||
|
|
||||||
return (r << 11) | (g << 5) | b;
|
return (r << 11) | (g << 5) | b;
|
||||||
}
|
}
|
||||||
|
|
||||||
void display_pixeldata(uint16_t c) {
|
void gamma_correct_buffer_to_display(void) {
|
||||||
|
// Gamma correct all the pixels in BUFFER_TO_DISPLAY.
|
||||||
|
pixel_color *pixels = (pixel_color *)BUFFER_TO_DISPLAY->pixels;
|
||||||
|
for (int y = 0; y < BUFFER_TO_DISPLAY->h; y++) {
|
||||||
|
for (int x = 0; x < BUFFER_TO_DISPLAY->w; x++) {
|
||||||
|
int index = y * BUFFER_TO_DISPLAY->pitch / 2 + x;
|
||||||
|
pixels[index] = gamma_correct(pixels[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_pixeldata(pixel_color c) {
|
||||||
#if defined TREZOR_MODEL_1 || defined TREZOR_MODEL_R
|
#if defined TREZOR_MODEL_1 || defined TREZOR_MODEL_R
|
||||||
// set to white if highest bits of all R, G, B values are set to 1
|
// set to white if highest bits of all R, G, B values are set to 1
|
||||||
// bin(10000 100000 10000) = hex(0x8410)
|
// bin(10000 100000 10000) = hex(0x8410)
|
||||||
// otherwise set to black
|
// otherwise set to black
|
||||||
c = (c & 0x8410) ? 0xFFFF : 0x0000;
|
c = (c & 0x8410) ? 0xFFFF : 0x0000;
|
||||||
#elif defined TREZOR_MODEL_T
|
|
||||||
c = gamma_correct(c);
|
|
||||||
#endif
|
#endif
|
||||||
if (!RENDERER) {
|
if (!RENDERER) {
|
||||||
display_init();
|
display_init();
|
||||||
}
|
}
|
||||||
if (PIXELWINDOW.pos.x <= PIXELWINDOW.end.x &&
|
if (PIXELWINDOW.pos.x <= PIXELWINDOW.end.x &&
|
||||||
PIXELWINDOW.pos.y <= PIXELWINDOW.end.y) {
|
PIXELWINDOW.pos.y <= PIXELWINDOW.end.y) {
|
||||||
((uint16_t *)
|
((pixel_color *)
|
||||||
BUFFER->pixels)[PIXELWINDOW.pos.x + PIXELWINDOW.pos.y * BUFFER->pitch /
|
BUFFER->pixels)[PIXELWINDOW.pos.x + PIXELWINDOW.pos.y * BUFFER->pitch /
|
||||||
sizeof(uint16_t)] = c;
|
sizeof(pixel_color)] = c;
|
||||||
}
|
}
|
||||||
PIXELWINDOW.pos.x++;
|
PIXELWINDOW.pos.x++;
|
||||||
if (PIXELWINDOW.pos.x > PIXELWINDOW.end.x) {
|
if (PIXELWINDOW.pos.x > PIXELWINDOW.end.x) {
|
||||||
@ -145,6 +155,7 @@ void display_init_seq(void) {}
|
|||||||
void display_deinit(void) {
|
void display_deinit(void) {
|
||||||
SDL_FreeSurface(PREV_SAVED);
|
SDL_FreeSurface(PREV_SAVED);
|
||||||
SDL_FreeSurface(BUFFER);
|
SDL_FreeSurface(BUFFER);
|
||||||
|
SDL_FreeSurface(BUFFER_TO_DISPLAY);
|
||||||
if (BACKGROUND != NULL) {
|
if (BACKGROUND != NULL) {
|
||||||
SDL_DestroyTexture(BACKGROUND);
|
SDL_DestroyTexture(BACKGROUND);
|
||||||
}
|
}
|
||||||
@ -167,6 +178,15 @@ void display_init(void) {
|
|||||||
}
|
}
|
||||||
atexit(display_deinit);
|
atexit(display_deinit);
|
||||||
|
|
||||||
|
// Not doing gamma correction for "dummy" SDL driver
|
||||||
|
// (not to slow down device/UI tests)
|
||||||
|
char *sdl_env = getenv("SDL_VIDEODRIVER");
|
||||||
|
if (sdl_env && strcmp(sdl_env, "dummy") == 0) {
|
||||||
|
DO_GAMMA_CORRECTION = false;
|
||||||
|
} else {
|
||||||
|
DO_GAMMA_CORRECTION = true;
|
||||||
|
}
|
||||||
|
|
||||||
char *window_title = NULL;
|
char *window_title = NULL;
|
||||||
char *window_title_alloc = NULL;
|
char *window_title_alloc = NULL;
|
||||||
if (asprintf(&window_title_alloc, "Trezor^emu: %s", profile_name()) > 0) {
|
if (asprintf(&window_title_alloc, "Trezor^emu: %s", profile_name()) > 0) {
|
||||||
@ -200,6 +220,9 @@ void display_init(void) {
|
|||||||
SDL_RenderClear(RENDERER);
|
SDL_RenderClear(RENDERER);
|
||||||
BUFFER = SDL_CreateRGBSurface(0, MAX_DISPLAY_RESX, MAX_DISPLAY_RESY, 16,
|
BUFFER = SDL_CreateRGBSurface(0, MAX_DISPLAY_RESX, MAX_DISPLAY_RESY, 16,
|
||||||
0xF800, 0x07E0, 0x001F, 0x0000);
|
0xF800, 0x07E0, 0x001F, 0x0000);
|
||||||
|
BUFFER_TO_DISPLAY =
|
||||||
|
SDL_CreateRGBSurface(0, MAX_DISPLAY_RESX, MAX_DISPLAY_RESY, 16, 0xF800,
|
||||||
|
0x07E0, 0x001F, 0x0000);
|
||||||
TEXTURE = SDL_CreateTexture(RENDERER, SDL_PIXELFORMAT_RGB565,
|
TEXTURE = SDL_CreateTexture(RENDERER, SDL_PIXELFORMAT_RGB565,
|
||||||
SDL_TEXTUREACCESS_STREAMING, DISPLAY_RESX,
|
SDL_TEXTUREACCESS_STREAMING, DISPLAY_RESX,
|
||||||
DISPLAY_RESY);
|
DISPLAY_RESY);
|
||||||
@ -272,7 +295,17 @@ void display_refresh(void) {
|
|||||||
} else {
|
} else {
|
||||||
SDL_RenderClear(RENDERER);
|
SDL_RenderClear(RENDERER);
|
||||||
}
|
}
|
||||||
SDL_UpdateTexture(TEXTURE, NULL, BUFFER->pixels, BUFFER->pitch);
|
// Fill BUFFER_TO_DISPLAY with BUFFER data
|
||||||
|
SDL_BlitSurface(BUFFER, NULL, BUFFER_TO_DISPLAY, NULL);
|
||||||
|
#if defined TREZOR_MODEL_T
|
||||||
|
// Gamma-correcting the display buffer for model T when wanted
|
||||||
|
if (DO_GAMMA_CORRECTION) {
|
||||||
|
gamma_correct_buffer_to_display();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// Show the display buffer
|
||||||
|
SDL_UpdateTexture(TEXTURE, NULL, BUFFER_TO_DISPLAY->pixels,
|
||||||
|
BUFFER_TO_DISPLAY->pitch);
|
||||||
#define BACKLIGHT_NORMAL 150
|
#define BACKLIGHT_NORMAL 150
|
||||||
SDL_SetTextureAlphaMod(TEXTURE,
|
SDL_SetTextureAlphaMod(TEXTURE,
|
||||||
MIN(255, 255 * DISPLAY_BACKLIGHT / BACKLIGHT_NORMAL));
|
MIN(255, 255 * DISPLAY_BACKLIGHT / BACKLIGHT_NORMAL));
|
||||||
|
Loading…
Reference in New Issue
Block a user