2019-05-17 09:15:25 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
2019-11-11 23:45:21 +00:00
|
|
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2019-05-17 09:15:25 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include "display_indev.h"
|
|
|
|
#include "sys/time.h"
|
|
|
|
#include "SDL2/SDL.h"
|
|
|
|
#define MONITOR_HOR_RES 320
|
|
|
|
#define MONITOR_VER_RES 240
|
|
|
|
#ifndef MONITOR_ZOOM
|
2021-11-15 04:48:35 +00:00
|
|
|
#define MONITOR_ZOOM 1
|
2019-05-17 09:15:25 +00:00
|
|
|
#endif
|
2021-11-15 04:48:35 +00:00
|
|
|
#define SDL_REFR_PERIOD 50
|
|
|
|
void
|
|
|
|
monitor_sdl_init(void);
|
|
|
|
void
|
|
|
|
monitor_sdl_refr_core(void);
|
|
|
|
void
|
|
|
|
monitor_sdl_clean_up(void);
|
2019-05-17 09:15:25 +00:00
|
|
|
static uint32_t tft_fb[MONITOR_HOR_RES * MONITOR_VER_RES];
|
|
|
|
|
2021-11-15 04:48:35 +00:00
|
|
|
void
|
|
|
|
display_vdb_write(void *buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
|
|
|
|
lv_color_t *color, lv_opa_t opa)
|
2019-05-17 09:15:25 +00:00
|
|
|
{
|
|
|
|
unsigned char *buf_xy = buf + 4 * x + 4 * y * buf_w;
|
2021-11-15 04:48:35 +00:00
|
|
|
lv_color_t *temp = (lv_color_t *)buf_xy;
|
2019-05-17 09:15:25 +00:00
|
|
|
*temp = *color;
|
|
|
|
/*
|
|
|
|
if (opa != LV_OPA_COVER) {
|
|
|
|
lv_color_t mix_color;
|
|
|
|
|
|
|
|
mix_color.red = *buf_xy;
|
|
|
|
mix_color.green = *(buf_xy+1);
|
|
|
|
mix_color.blue = *(buf_xy+2);
|
|
|
|
color = lv_color_mix(color, mix_color, opa);
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
}
|
2021-11-15 04:48:35 +00:00
|
|
|
int
|
|
|
|
time_get_ms()
|
2019-05-17 09:15:25 +00:00
|
|
|
{
|
|
|
|
static struct timeval tv;
|
|
|
|
gettimeofday(&tv, NULL);
|
|
|
|
long long time_in_mill = (tv.tv_sec) * 1000 + (tv.tv_usec) / 1000;
|
|
|
|
|
2021-11-15 04:48:35 +00:00
|
|
|
return (int)time_in_mill;
|
2019-05-17 09:15:25 +00:00
|
|
|
}
|
|
|
|
|
2021-11-15 04:48:35 +00:00
|
|
|
SDL_Window *window;
|
|
|
|
SDL_Renderer *renderer;
|
|
|
|
SDL_Texture *texture;
|
2019-05-17 09:15:25 +00:00
|
|
|
static volatile bool sdl_inited = false;
|
|
|
|
static volatile bool sdl_refr_qry = false;
|
|
|
|
static volatile bool sdl_quit_qry = false;
|
|
|
|
|
2021-11-15 04:48:35 +00:00
|
|
|
void
|
|
|
|
monitor_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
|
|
|
const lv_color_t *color_p)
|
2019-05-17 09:15:25 +00:00
|
|
|
{
|
|
|
|
/*Return if the area is out the screen*/
|
|
|
|
if (x2 < 0 || y2 < 0 || x1 > MONITOR_HOR_RES - 1
|
2021-11-15 04:48:35 +00:00
|
|
|
|| y1 > MONITOR_VER_RES - 1) {
|
2019-05-17 09:15:25 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t y;
|
|
|
|
uint32_t w = x2 - x1 + 1;
|
|
|
|
for (y = y1; y <= y2; y++) {
|
|
|
|
memcpy(&tft_fb[y * MONITOR_HOR_RES + x1], color_p,
|
2021-11-15 04:48:35 +00:00
|
|
|
w * sizeof(lv_color_t));
|
2019-05-17 09:15:25 +00:00
|
|
|
|
|
|
|
color_p += w;
|
|
|
|
}
|
|
|
|
sdl_refr_qry = true;
|
|
|
|
|
|
|
|
/*IMPORTANT! It must be called to tell the system the flush is ready*/
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Fill out the marked area with a color
|
|
|
|
* @param x1 left coordinate
|
|
|
|
* @param y1 top coordinate
|
|
|
|
* @param x2 right coordinate
|
|
|
|
* @param y2 bottom coordinate
|
|
|
|
* @param color fill color
|
|
|
|
*/
|
2021-11-15 04:48:35 +00:00
|
|
|
void
|
|
|
|
monitor_fill(int32_t x1, int32_t y1, int32_t x2, int32_t y2, lv_color_t color)
|
2019-05-17 09:15:25 +00:00
|
|
|
{
|
|
|
|
/*Return if the area is out the screen*/
|
|
|
|
if (x2 < 0)
|
|
|
|
return;
|
|
|
|
if (y2 < 0)
|
|
|
|
return;
|
|
|
|
if (x1 > MONITOR_HOR_RES - 1)
|
|
|
|
return;
|
|
|
|
if (y1 > MONITOR_VER_RES - 1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/*Truncate the area to the screen*/
|
|
|
|
int32_t act_x1 = x1 < 0 ? 0 : x1;
|
|
|
|
int32_t act_y1 = y1 < 0 ? 0 : y1;
|
|
|
|
int32_t act_x2 = x2 > MONITOR_HOR_RES - 1 ? MONITOR_HOR_RES - 1 : x2;
|
|
|
|
int32_t act_y2 = y2 > MONITOR_VER_RES - 1 ? MONITOR_VER_RES - 1 : y2;
|
|
|
|
|
|
|
|
int32_t x;
|
|
|
|
int32_t y;
|
2021-11-15 04:48:35 +00:00
|
|
|
uint32_t color32 = color.full; // lv_color_to32(color);
|
2019-05-17 09:15:25 +00:00
|
|
|
|
|
|
|
for (x = act_x1; x <= act_x2; x++) {
|
|
|
|
for (y = act_y1; y <= act_y2; y++) {
|
|
|
|
tft_fb[y * MONITOR_HOR_RES + x] = color32;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sdl_refr_qry = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Put a color map to the marked area
|
|
|
|
* @param x1 left coordinate
|
|
|
|
* @param y1 top coordinate
|
|
|
|
* @param x2 right coordinate
|
|
|
|
* @param y2 bottom coordinate
|
|
|
|
* @param color_p an array of colors
|
|
|
|
*/
|
2021-11-15 04:48:35 +00:00
|
|
|
void
|
|
|
|
monitor_map(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
|
|
|
const lv_color_t *color_p)
|
2019-05-17 09:15:25 +00:00
|
|
|
{
|
|
|
|
/*Return if the area is out the screen*/
|
|
|
|
if (x2 < 0)
|
|
|
|
return;
|
|
|
|
if (y2 < 0)
|
|
|
|
return;
|
|
|
|
if (x1 > MONITOR_HOR_RES - 1)
|
|
|
|
return;
|
|
|
|
if (y1 > MONITOR_VER_RES - 1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/*Truncate the area to the screen*/
|
|
|
|
int32_t act_x1 = x1 < 0 ? 0 : x1;
|
|
|
|
int32_t act_y1 = y1 < 0 ? 0 : y1;
|
|
|
|
int32_t act_x2 = x2 > MONITOR_HOR_RES - 1 ? MONITOR_HOR_RES - 1 : x2;
|
|
|
|
int32_t act_y2 = y2 > MONITOR_VER_RES - 1 ? MONITOR_VER_RES - 1 : y2;
|
|
|
|
|
|
|
|
int32_t x;
|
|
|
|
int32_t y;
|
|
|
|
|
|
|
|
for (y = act_y1; y <= act_y2; y++) {
|
|
|
|
for (x = act_x1; x <= act_x2; x++) {
|
2021-11-15 04:48:35 +00:00
|
|
|
tft_fb[y * MONITOR_HOR_RES + x] =
|
|
|
|
color_p->full; // lv_color_to32(*color_p);
|
2019-05-17 09:15:25 +00:00
|
|
|
color_p++;
|
|
|
|
}
|
|
|
|
|
|
|
|
color_p += x2 - act_x2;
|
|
|
|
}
|
|
|
|
|
|
|
|
sdl_refr_qry = true;
|
|
|
|
}
|
|
|
|
|
2021-11-15 04:48:35 +00:00
|
|
|
void
|
|
|
|
display_init(void)
|
|
|
|
{}
|
2019-05-17 09:15:25 +00:00
|
|
|
|
2021-11-15 04:48:35 +00:00
|
|
|
void
|
|
|
|
display_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
|
|
|
const lv_color_t *color_p)
|
2019-05-17 09:15:25 +00:00
|
|
|
{
|
|
|
|
monitor_flush(x1, y1, x2, y2, color_p);
|
|
|
|
}
|
2021-11-15 04:48:35 +00:00
|
|
|
void
|
|
|
|
display_fill(int32_t x1, int32_t y1, int32_t x2, int32_t y2, lv_color_t color_p)
|
2019-05-17 09:15:25 +00:00
|
|
|
{
|
|
|
|
monitor_fill(x1, y1, x2, y2, color_p);
|
|
|
|
}
|
2021-11-15 04:48:35 +00:00
|
|
|
void
|
|
|
|
display_map(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
|
|
|
const lv_color_t *color_p)
|
2019-05-17 09:15:25 +00:00
|
|
|
{
|
|
|
|
monitor_map(x1, y1, x2, y2, color_p);
|
|
|
|
}
|
|
|
|
|
2021-11-15 04:48:35 +00:00
|
|
|
bool
|
|
|
|
display_input_read(lv_indev_data_t *data)
|
2019-05-17 09:15:25 +00:00
|
|
|
{
|
|
|
|
return mouse_read(data);
|
|
|
|
}
|
|
|
|
|
2021-11-15 04:48:35 +00:00
|
|
|
void
|
|
|
|
display_deinit(void)
|
|
|
|
{}
|
2019-05-17 09:15:25 +00:00
|
|
|
|
2021-11-15 04:48:35 +00:00
|
|
|
int
|
|
|
|
monitor_sdl_refr_thread(void *param)
|
2019-05-17 09:15:25 +00:00
|
|
|
{
|
2021-11-15 04:48:35 +00:00
|
|
|
(void)param;
|
2019-05-17 09:15:25 +00:00
|
|
|
|
|
|
|
/*If not OSX initialize SDL in the Thread*/
|
|
|
|
monitor_sdl_init();
|
|
|
|
/*Run until quit event not arrives*/
|
|
|
|
while (sdl_quit_qry == false) {
|
|
|
|
/*Refresh handling*/
|
|
|
|
monitor_sdl_refr_core();
|
|
|
|
}
|
|
|
|
|
|
|
|
monitor_sdl_clean_up();
|
|
|
|
exit(0);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-11-15 04:48:35 +00:00
|
|
|
void
|
|
|
|
monitor_sdl_refr_core(void)
|
2019-05-17 09:15:25 +00:00
|
|
|
{
|
|
|
|
if (sdl_refr_qry != false) {
|
|
|
|
sdl_refr_qry = false;
|
|
|
|
|
|
|
|
SDL_UpdateTexture(texture, NULL, tft_fb,
|
2021-11-15 04:48:35 +00:00
|
|
|
MONITOR_HOR_RES * sizeof(uint32_t));
|
2019-05-17 09:15:25 +00:00
|
|
|
SDL_RenderClear(renderer);
|
2021-11-15 04:48:35 +00:00
|
|
|
/*Test: Draw a background to test transparent screens
|
|
|
|
* (LV_COLOR_SCREEN_TRANSP)*/
|
|
|
|
// SDL_SetRenderDrawColor(renderer, 0xff, 0, 0, 0xff);
|
|
|
|
// SDL_Rect r;
|
|
|
|
// r.x = 0; r.y = 0; r.w = MONITOR_HOR_RES; r.w =
|
|
|
|
// MONITOR_VER_RES; SDL_RenderDrawRect(renderer, &r);
|
2019-05-17 09:15:25 +00:00
|
|
|
/*Update the renderer with the texture containing the rendered image*/
|
|
|
|
SDL_RenderCopy(renderer, texture, NULL, NULL);
|
|
|
|
SDL_RenderPresent(renderer);
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_Event event;
|
|
|
|
while (SDL_PollEvent(&event)) {
|
|
|
|
#if USE_MOUSE != 0
|
|
|
|
mouse_handler(&event);
|
|
|
|
#endif
|
|
|
|
if ((&event)->type == SDL_WINDOWEVENT) {
|
|
|
|
switch ((&event)->window.event) {
|
|
|
|
#if SDL_VERSION_ATLEAST(2, 0, 5)
|
2021-11-15 04:48:35 +00:00
|
|
|
case SDL_WINDOWEVENT_TAKE_FOCUS:
|
2019-05-17 09:15:25 +00:00
|
|
|
#endif
|
2021-11-15 04:48:35 +00:00
|
|
|
case SDL_WINDOWEVENT_EXPOSED:
|
|
|
|
|
|
|
|
SDL_UpdateTexture(texture, NULL, tft_fb,
|
|
|
|
MONITOR_HOR_RES * sizeof(uint32_t));
|
|
|
|
SDL_RenderClear(renderer);
|
|
|
|
SDL_RenderCopy(renderer, texture, NULL, NULL);
|
|
|
|
SDL_RenderPresent(renderer);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2019-05-17 09:15:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*Sleep some time*/
|
|
|
|
SDL_Delay(SDL_REFR_PERIOD);
|
|
|
|
}
|
2021-11-15 04:48:35 +00:00
|
|
|
int
|
|
|
|
quit_filter(void *userdata, SDL_Event *event)
|
2019-05-17 09:15:25 +00:00
|
|
|
{
|
2021-11-15 04:48:35 +00:00
|
|
|
(void)userdata;
|
2019-05-17 09:15:25 +00:00
|
|
|
|
|
|
|
if (event->type == SDL_QUIT) {
|
|
|
|
sdl_quit_qry = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2021-11-15 04:48:35 +00:00
|
|
|
void
|
|
|
|
monitor_sdl_clean_up(void)
|
2019-05-17 09:15:25 +00:00
|
|
|
{
|
|
|
|
SDL_DestroyTexture(texture);
|
|
|
|
SDL_DestroyRenderer(renderer);
|
|
|
|
SDL_DestroyWindow(window);
|
|
|
|
SDL_Quit();
|
|
|
|
}
|
|
|
|
|
2021-11-15 04:48:35 +00:00
|
|
|
void
|
|
|
|
monitor_sdl_init(void)
|
2019-05-17 09:15:25 +00:00
|
|
|
{
|
|
|
|
/*Initialize the SDL*/
|
|
|
|
SDL_Init(SDL_INIT_VIDEO);
|
|
|
|
|
|
|
|
SDL_SetEventFilter(quit_filter, NULL);
|
|
|
|
|
2021-11-15 04:48:35 +00:00
|
|
|
window = SDL_CreateWindow(
|
|
|
|
"TFT Simulator", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
|
|
|
|
MONITOR_HOR_RES * MONITOR_ZOOM, MONITOR_VER_RES * MONITOR_ZOOM,
|
|
|
|
0); /*last param. SDL_WINDOW_BORDERLESS to hide borders*/
|
2019-05-17 09:15:25 +00:00
|
|
|
|
|
|
|
renderer = SDL_CreateRenderer(window, -1, 0);
|
|
|
|
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888,
|
2021-11-15 04:48:35 +00:00
|
|
|
SDL_TEXTUREACCESS_STATIC, MONITOR_HOR_RES,
|
|
|
|
MONITOR_VER_RES);
|
2019-05-17 09:15:25 +00:00
|
|
|
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
|
|
|
|
|
|
|
/*Initialize the frame buffer to gray (77 is an empirical value) */
|
|
|
|
memset(tft_fb, 0x44, MONITOR_HOR_RES * MONITOR_VER_RES * sizeof(uint32_t));
|
|
|
|
SDL_UpdateTexture(texture, NULL, tft_fb,
|
2021-11-15 04:48:35 +00:00
|
|
|
MONITOR_HOR_RES * sizeof(uint32_t));
|
2019-05-17 09:15:25 +00:00
|
|
|
sdl_refr_qry = true;
|
|
|
|
sdl_inited = true;
|
|
|
|
}
|
|
|
|
|
2021-11-15 04:48:35 +00:00
|
|
|
void
|
|
|
|
display_SDL_init()
|
2019-05-17 09:15:25 +00:00
|
|
|
{
|
|
|
|
SDL_CreateThread(monitor_sdl_refr_thread, "sdl_refr", NULL);
|
|
|
|
while (sdl_inited == false)
|
|
|
|
; /*Wait until 'sdl_refr' initializes the SDL*/
|
|
|
|
}
|