123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304 |
- /* MegaZeux
- *
- * Copyright (C) 2007 Alan Williams <mralert@gmail.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
- #include <stdlib.h>
- #include "platform.h"
- #include "graphics.h"
- #include "render.h"
- #include "render_layer.h"
- #include "render_sdl.h"
- #include "renderers.h"
- #include "util.h"
- #include "yuv.h"
- #if SDL_VERSION_ATLEAST(2,0,0)
- #error Overlay renderer no longer supported for SDL 2+. Use softscale!
- #endif
- #define YUV1_OVERLAY_WIDTH (SCREEN_PIX_W * 2)
- #define YUV1_OVERLAY_HEIGHT SCREEN_PIX_H
- #define YUV2_OVERLAY_WIDTH SCREEN_PIX_W
- #define YUV2_OVERLAY_HEIGHT SCREEN_PIX_H
- struct yuv_render_data
- {
- struct sdl_render_data sdl;
- void (*set_colors_mzx)(struct graphics_data *, Uint32 *, Uint8, Uint8);
- Uint32 (*rgb_to_yuv)(Uint8 r, Uint8 g, Uint8 b);
- Uint32 bpp;
- Uint32 w;
- Uint32 h;
- };
- static boolean yuv_set_video_mode_size(struct graphics_data *graphics,
- int width, int height, int depth, boolean fullscreen, boolean resize,
- int yuv_width, int yuv_height)
- {
- struct yuv_render_data *render_data = graphics->render_data;
- // the YUV renderer _requires_ 32bit colour
- render_data->sdl.screen = SDL_SetVideoMode(width, height, 32,
- sdl_flags(depth, fullscreen, false, resize) | SDL_ANYFORMAT);
- if(!render_data->sdl.screen)
- goto err_free;
- // try with a YUY2 pixel format first
- render_data->rgb_to_yuv = rgb_to_yuy2;
- render_data->set_colors_mzx = yuy2_subsample_set_colors_mzx;
- render_data->sdl.overlay = SDL_CreateYUVOverlay(yuv_width, yuv_height,
- SDL_YUY2_OVERLAY, render_data->sdl.screen);
- // didn't work, try with a UYVY pixel format next
- if(!render_data->sdl.overlay)
- {
- render_data->rgb_to_yuv = rgb_to_uyvy;
- render_data->set_colors_mzx = uyvy_subsample_set_colors_mzx;
- render_data->sdl.overlay = SDL_CreateYUVOverlay(yuv_width, yuv_height,
- SDL_UYVY_OVERLAY, render_data->sdl.screen);
- }
- // Since we support this format now too, might as well try.
- if(!render_data->sdl.overlay)
- {
- render_data->rgb_to_yuv = rgb_to_yvyu;
- render_data->set_colors_mzx = yvyu_subsample_set_colors_mzx;
- render_data->sdl.overlay = SDL_CreateYUVOverlay(yuv_width, yuv_height,
- SDL_YVYU_OVERLAY, render_data->sdl.screen);
- }
- // failed to create an overlay
- if(!render_data->sdl.overlay)
- goto err_free;
- render_data->w = width;
- render_data->h = height;
- return true;
- err_free:
- sdl_destruct_window(graphics);
- return false;
- }
- static boolean yuv1_set_video_mode(struct graphics_data *graphics,
- int width, int height, int depth, boolean fullscreen, boolean resize)
- {
- struct yuv_render_data *render_data = graphics->render_data;
- render_data->bpp = 32;
- return yuv_set_video_mode_size(graphics, width, height, depth, fullscreen,
- resize, YUV1_OVERLAY_WIDTH, YUV1_OVERLAY_HEIGHT);
- }
- static boolean yuv2_set_video_mode(struct graphics_data *graphics,
- int width, int height, int depth, boolean fullscreen, boolean resize)
- {
- struct yuv_render_data *render_data = graphics->render_data;
- render_data->bpp = 16;
- return yuv_set_video_mode_size(graphics, width, height, depth, fullscreen,
- resize, YUV2_OVERLAY_WIDTH, YUV2_OVERLAY_HEIGHT);
- }
- static boolean yuv_init_video(struct graphics_data *graphics,
- struct config_info *conf)
- {
- struct yuv_render_data *render_data = cmalloc(sizeof(struct yuv_render_data));
- if(!render_data)
- return false;
- memset(render_data, 0, sizeof(struct yuv_render_data));
- graphics->render_data = render_data;
- graphics->allow_resize = conf->allow_resize;
- graphics->ratio = conf->video_ratio;
- if(!set_video_mode())
- {
- free(render_data);
- graphics->render_data = NULL;
- return false;
- }
- return true;
- }
- static void yuv_free_video(struct graphics_data *graphics)
- {
- sdl_destruct_window(graphics);
- free(graphics->render_data);
- graphics->render_data = NULL;
- }
- static boolean yuv_check_video_mode(struct graphics_data *graphics,
- int width, int height, int depth, boolean fullscreen, boolean resize)
- {
- return SDL_VideoModeOK(width, height, 32,
- sdl_flags(depth, fullscreen, false, resize) | SDL_ANYFORMAT);
- }
- static void yuv_update_colors(struct graphics_data *graphics,
- struct rgb_color *palette, Uint32 count)
- {
- struct yuv_render_data *render_data = graphics->render_data;
- Uint32 i;
- for(i = 0; i < count; i++)
- {
- graphics->flat_intensity_palette[i] =
- render_data->rgb_to_yuv(palette[i].r, palette[i].g, palette[i].b);
- }
- }
- static void yuv_lock_overlay(struct yuv_render_data *render_data,
- Uint32 **pixels, Uint32 *pitch)
- {
- SDL_LockYUVOverlay(render_data->sdl.overlay);
- *pixels = (Uint32 *)render_data->sdl.overlay->pixels[0];
- *pitch = render_data->sdl.overlay->pitches[0];
- }
- static void yuv_unlock_overlay(struct yuv_render_data *render_data)
- {
- SDL_UnlockYUVOverlay(render_data->sdl.overlay);
- }
- static void yuv_render_graph(struct graphics_data *graphics)
- {
- struct yuv_render_data *render_data = graphics->render_data;
- Uint32 mode = graphics->screen_mode;
- Uint32 bpp = render_data->bpp;
- Uint32 *pixels;
- Uint32 pitch;
- yuv_lock_overlay(render_data, &pixels, &pitch);
- if(bpp == 16)
- {
- // Subsampled mode
- if(!mode)
- render_graph16((Uint16 *)pixels, pitch, graphics,
- render_data->set_colors_mzx);
- else
- render_graph16((Uint16 *)pixels, pitch, graphics, set_colors32[mode]);
- }
- else
- {
- if(!mode)
- render_graph32(pixels, pitch, graphics, set_colors32[mode]);
- else
- render_graph32s(pixels, pitch, graphics, set_colors32[mode]);
- }
- yuv_unlock_overlay(render_data);
- }
- static void yuv1_render_layer(struct graphics_data *graphics,
- struct video_layer *layer)
- {
- struct yuv_render_data *render_data = graphics->render_data;
- Uint32 bpp = render_data->bpp;
- Uint32 *pixels;
- Uint32 pitch;
- yuv_lock_overlay(render_data, &pixels, &pitch);
- render_layer(pixels, bpp, pitch, graphics, layer);
- yuv_unlock_overlay(render_data);
- }
- static void yuv_render_cursor(struct graphics_data *graphics,
- Uint32 x, Uint32 y, Uint16 color, Uint8 lines, Uint8 offset)
- {
- struct yuv_render_data *render_data = graphics->render_data;
- Uint32 bpp = render_data->bpp;
- Uint32 *pixels;
- Uint32 pitch;
- yuv_lock_overlay(render_data, &pixels, &pitch);
- render_cursor(pixels, pitch, bpp, x, y,
- graphics->flat_intensity_palette[color], lines, offset);
- yuv_unlock_overlay(render_data);
- }
- static void yuv_render_mouse(struct graphics_data *graphics,
- Uint32 x, Uint32 y, Uint8 w, Uint8 h)
- {
- struct yuv_render_data *render_data = graphics->render_data;
- Uint32 bpp = render_data->bpp;
- Uint32 *pixels;
- Uint32 pitch;
- yuv_lock_overlay(render_data, &pixels, &pitch);
- render_mouse(pixels, pitch, bpp, x, y, 0xFFFFFFFF, 0x0, w, h);
- yuv_unlock_overlay(render_data);
- }
- static void yuv_sync_screen(struct graphics_data *graphics)
- {
- struct yuv_render_data *render_data = graphics->render_data;
- int width = render_data->w, v_width;
- int height = render_data->h, v_height;
- SDL_Rect rect;
- // FIXME: Putting this here is suboptimal
- fix_viewport_ratio(width, height, &v_width, &v_height, graphics->ratio);
- rect.x = (width - v_width) >> 1;
- rect.y = (height - v_height) >> 1;
- rect.w = v_width;
- rect.h = v_height;
- SDL_DisplayYUVOverlay(render_data->sdl.overlay, &rect);
- }
- void render_yuv1_register(struct renderer *renderer)
- {
- memset(renderer, 0, sizeof(struct renderer));
- renderer->init_video = yuv_init_video;
- renderer->free_video = yuv_free_video;
- renderer->check_video_mode = yuv_check_video_mode;
- renderer->set_video_mode = yuv1_set_video_mode;
- renderer->update_colors = yuv_update_colors;
- renderer->resize_screen = resize_screen_standard;
- renderer->get_screen_coords = get_screen_coords_scaled;
- renderer->set_screen_coords = set_screen_coords_scaled;
- renderer->render_graph = yuv_render_graph;
- renderer->render_layer = yuv1_render_layer;
- renderer->render_cursor = yuv_render_cursor;
- renderer->render_mouse = yuv_render_mouse;
- renderer->sync_screen = yuv_sync_screen;
- }
- void render_yuv2_register(struct renderer *renderer)
- {
- render_yuv1_register(renderer);
- renderer->set_video_mode = yuv2_set_video_mode;
- renderer->render_layer = NULL;
- }
|