1 /**
2  * \file   videoarch.h
3  * \brief  Native GTK3 graphics routines
4  *
5  * \author Ettore Perazzoli
6  * \author Teemu Rantanen <tvr@cs.hut.fi>
7  * \author Andreas Boose <viceteam@t-online.de>
8  * \author Michael C. Martin <mcmartin@gmail.com>
9  */
10 
11 /*
12  * This file is part of VICE, the Versatile Commodore Emulator.
13  * See README for copyright notice.
14  *
15  *  This program is free software; you can redistribute it and/or modify
16  *  it under the terms of the GNU General Public License as published by
17  *  the Free Software Foundation; either version 2 of the License, or
18  *  (at your option) any later version.
19  *
20  *  This program is distributed in the hope that it will be useful,
21  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
22  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  *  GNU General Public License for more details.
24  *
25  *  You should have received a copy of the GNU General Public License
26  *  along with this program; if not, write to the Free Software
27  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28  *  02111-1307  USA.
29  *
30  */
31 #ifndef VICE_VIDEOARCH_H
32 #define VICE_VIDEOARCH_H
33 
34 #include "vice.h"
35 
36 #include "viewport.h"
37 #include "video.h"
38 
39 #include <gtk/gtk.h>
40 #include <pthread.h>
41 
42 
43 /** \brief  Enum for rendering backends for the Gtk3 port
44  *
45  * Currently OpenGL and DirectX map to the same integer value since that's how
46  * our current 'GtkBackend' resource works: 0 = Cario (SW), 1 = HW (OS-dependent).
47  * The Metal and Vulkan enums are added for future renderers, should we add them.
48  */
49 enum {
50     VICE_RENDER_BACKEND_CAIRO = 0,      /**< Cairo (software) rendering */
51     VICE_RENDER_BACKEND_OPENGL = 1,     /**< OpenGL rendering (unix, mac) */
52     VICE_RENDER_BACKEND_DIRECTX = 1,    /**< DirectX rendering (windows) */
53     VICE_RENDER_BACKEND_METAL = 2,      /**< Metal rendering (unsupported) */
54     VICE_RENDER_BACKEND_VULKAN = 3      /**< Vulkan rendering (unsupported) */
55 };
56 
57 
58 struct vice_renderer_backend_s;
59 
60 /**
61  * \brief Master data structure for a machine window's primary display.
62  */
63 typedef struct video_canvas_s {
64     /** \brief Nonzero if it is safe to access other members of the
65      *         structure. */
66     unsigned int initialized;
67 
68     /** \brief Nonzero if the structure has been fully realized. */
69     unsigned int created;
70 
71     /** \brief Used to coordinate vice thread access */
72     pthread_mutex_t lock;
73 
74     /** \brief Top-level widget that contains the full contents of the
75      *         machine window. */
76     GtkWidget *grid;
77 
78     /** \brief Widget for mouse input and to size the rendering overlay.
79      */
80     GtkWidget *event_box;
81 
82     /** \brief The renderer backend selected for use this run. */
83     struct vice_renderer_backend_s *renderer_backend;
84 
85     /** \brief Data unique to the renderer backend. This value is
86      *         passed to all renderer methods. and is managed by
87      *         them. */
88     void *renderer_context;
89 
90     /** \brief Special "blank" cursor for cases where the mouse
91      *         pointer should disappear. */
92     GdkCursor *blank_ptr;
93 
94     /** \brief Special "target" cursor for active light pens. */
95     GdkCursor *pen_ptr;
96 
97     /** \brief Handle to the timer callback that will make the mouse
98      *         disappear if it's hovered for too long over the screen
99      *         display. */
100     guint still_frame_callback_id;
101 
102     /** \brief Light pen X coordinate, in window coordinates. */
103     int pen_x;
104 
105     /** \brief Light pen Y coordinate, in window coordinates. */
106     int pen_y;
107 
108     /** \brief Light pen button status. */
109     int pen_buttons;
110 
111     /** \brief Leftmost X coordinate of the actual machine's screen,
112      *         in window coordinates. */
113     double screen_origin_x;
114 
115     /** \brief Topmost Y coordinate of the actual machine's screen, in
116      *         window coordinates. */
117     double screen_origin_y;
118 
119     /** \brief Width of the actual machine's screen, in window
120      *         coordinates. */
121     double screen_display_w;
122 
123     /** \brief Height of the actual machine's screen, in window
124      *         coordinates. */
125     double screen_display_h;
126 
127     /** \brief Rendering configuration as seen by the emulator
128      *         core. */
129     struct video_render_config_s *videoconfig;
130 
131     /** \brief Drawing buffer as seen by the emulator core. */
132     struct draw_buffer_s *draw_buffer;
133 
134     /** \brief Display window as seen by the emulator core. */
135     struct viewport_s *viewport;
136 
137     /** \brief Machine screen geometry as seen by the emulator
138      *         core. */
139     struct geometry_s *geometry;
140 
141     /** \brief Color palette for translating display results into
142      *         window colors. */
143     struct palette_s *palette;
144 
145     /** \brief Methods for managing the draw buffer when the core
146      *         rasterizer handles it. */
147     struct video_draw_buffer_callback_s *video_draw_buffer_callback;
148 
149     /** \brief Which window contains this canvas.
150      *  \sa ui_resources_s::canvas The array this value indexes */
151     int window_index;
152 } video_canvas_t;
153 
154 /** \brief Rescale and reposition the screen inside the canvas if the
155  *         screen's size has been programatically changed.
156  *  \param canvas The canvas to adjust.
157  */
158 void video_canvas_adjust_aspect_ratio(struct video_canvas_s *canvas);
159 
160 /** \brief A collection of methods that abstract away the underlying
161  *         display API.
162  *
163  *  GTK3's default software rendering (Cairo) and its accelerated one
164  *  (OpenGL) use very different mechanisms for displaying (possibly
165  *  scaled) pixel content or incrementally updating it. These routines
166  *  let us keep those differences contained. */
167 typedef struct vice_renderer_backend_s {
168     /** \brief Add event handlers to the event box and create context.
169      *
170      *  \param canvas The canvas to initialise.
171      *  \return The newly created widget.
172      */
173     void (*initialise)(video_canvas_t *canvas);
174     /** \brief Creates or resizes the pixel buffer that this renderer
175      *         backend is using for the screen.
176      *
177      * This is an expensive operation if the width and height have
178      * changed since the last call.
179      *
180      * \param canvas The canvas being resized or initially created.
181      * \param width The new width for the machine's screen.
182      * \param height The new height for the machine's screen.
183      */
184     void (*update_context)(video_canvas_t *canvas,
185                            unsigned int width, unsigned int height);
186     /** \brief Clean up any resources used by this renderer backend,
187      *         in preparation for destruction or recreation.
188      *
189      *  \param canvas The canvas whose renderer_context is to be
190      *                deleted
191      */
192     void (*destroy_context)(video_canvas_t *canvas);
193     /** \brief Render pixels in the specified rectangle.
194      *
195      * This asks the emulator core to update the renderer context.
196      *
197      * \param canvas The canvas being rendered to
198      * \param xs     A parameter to forward to video_canvas_render()
199      * \param ys     A parameter to forward to video_canvas_render()
200      * \param xi     X coordinate of the leftmost pixel to update
201      * \param yi     Y coordinate of the topmost pixel to update
202      * \param w      Width of the rectangle to update
203      * \param h      Height of the rectangle to update
204      */
205     void (*refresh_rect)(video_canvas_t *canvas,
206                          unsigned int xs, unsigned int ys,
207                          unsigned int xi, unsigned int yi,
208                          unsigned int w, unsigned int h);
209     /** \brief Queue a redraw operation from the UI thread
210      *
211      * \param clock The window GtkFrameClock generating the event
212      * \param widget UI widget to queue a redraw for
213      */
214     void (*queue_redraw)(GdkFrameClock *clock, video_canvas_t *canvas);
215     /** \brief Initialize the palette for this renderer.
216      *
217      * \param canvas The canvas being initialized
218      */
219     void (*set_palette)(video_canvas_t *canvas);
220 } vice_renderer_backend_t;
221 
222 #endif
223