]>
Commit | Line | Data |
---|---|---|
cd2bc889 GH |
1 | /* |
2 | * QEMU graphical console -- opengl helper bits | |
3 | * | |
4 | * Copyright (c) 2014 Red Hat | |
5 | * | |
6 | * Authors: | |
7 | * Gerd Hoffmann <[email protected]> | |
8 | * | |
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
10 | * of this software and associated documentation files (the "Software"), to deal | |
11 | * in the Software without restriction, including without limitation the rights | |
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
13 | * copies of the Software, and to permit persons to whom the Software is | |
14 | * furnished to do so, subject to the following conditions: | |
15 | * | |
16 | * The above copyright notice and this permission notice shall be included in | |
17 | * all copies or substantial portions of the Software. | |
18 | * | |
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
22 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
25 | * THE SOFTWARE. | |
26 | */ | |
27 | #include "qemu-common.h" | |
28 | #include "ui/console.h" | |
29 | #include "ui/shader.h" | |
30 | ||
31 | #include "shader/texture-blit-vert.h" | |
32 | #include "shader/texture-blit-frag.h" | |
33 | ||
34 | struct ConsoleGLState { | |
35 | GLint texture_blit_prog; | |
36 | }; | |
37 | ||
38 | /* ---------------------------------------------------------------------- */ | |
39 | ||
40 | ConsoleGLState *console_gl_init_context(void) | |
41 | { | |
42 | ConsoleGLState *gls = g_new0(ConsoleGLState, 1); | |
43 | ||
44 | gls->texture_blit_prog = qemu_gl_create_compile_link_program | |
45 | (texture_blit_vert_src, texture_blit_frag_src); | |
46 | if (!gls->texture_blit_prog) { | |
47 | exit(1); | |
48 | } | |
49 | ||
50 | return gls; | |
51 | } | |
52 | ||
53 | void console_gl_fini_context(ConsoleGLState *gls) | |
54 | { | |
55 | if (!gls) { | |
56 | return; | |
57 | } | |
58 | g_free(gls); | |
59 | } | |
60 | ||
61 | bool console_gl_check_format(DisplayChangeListener *dcl, | |
62 | pixman_format_code_t format) | |
63 | { | |
64 | switch (format) { | |
65 | case PIXMAN_BE_b8g8r8x8: | |
66 | case PIXMAN_BE_b8g8r8a8: | |
67 | case PIXMAN_r5g6b5: | |
68 | return true; | |
69 | default: | |
70 | return false; | |
71 | } | |
72 | } | |
73 | ||
74 | void surface_gl_create_texture(ConsoleGLState *gls, | |
75 | DisplaySurface *surface) | |
76 | { | |
77 | assert(gls); | |
78 | assert(surface_stride(surface) % surface_bytes_per_pixel(surface) == 0); | |
79 | ||
80 | switch (surface->format) { | |
81 | case PIXMAN_BE_b8g8r8x8: | |
82 | case PIXMAN_BE_b8g8r8a8: | |
83 | surface->glformat = GL_BGRA_EXT; | |
84 | surface->gltype = GL_UNSIGNED_BYTE; | |
85 | break; | |
86 | case PIXMAN_r5g6b5: | |
87 | surface->glformat = GL_RGB; | |
88 | surface->gltype = GL_UNSIGNED_SHORT_5_6_5; | |
89 | break; | |
90 | default: | |
91 | g_assert_not_reached(); | |
92 | } | |
93 | ||
94 | glGenTextures(1, &surface->texture); | |
95 | glEnable(GL_TEXTURE_2D); | |
96 | glBindTexture(GL_TEXTURE_2D, surface->texture); | |
97 | glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, | |
98 | surface_stride(surface) / surface_bytes_per_pixel(surface)); | |
99 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, | |
100 | surface_width(surface), | |
101 | surface_height(surface), | |
102 | 0, surface->glformat, surface->gltype, | |
103 | surface_data(surface)); | |
104 | ||
105 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
106 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
107 | } | |
108 | ||
109 | void surface_gl_update_texture(ConsoleGLState *gls, | |
110 | DisplaySurface *surface, | |
111 | int x, int y, int w, int h) | |
112 | { | |
113 | uint8_t *data = (void *)surface_data(surface); | |
114 | ||
115 | assert(gls); | |
116 | ||
117 | glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, | |
118 | surface_stride(surface) / surface_bytes_per_pixel(surface)); | |
119 | glTexSubImage2D(GL_TEXTURE_2D, 0, | |
120 | x, y, w, h, | |
121 | surface->glformat, surface->gltype, | |
122 | data + surface_stride(surface) * y | |
123 | + surface_bytes_per_pixel(surface) * x); | |
124 | } | |
125 | ||
126 | void surface_gl_render_texture(ConsoleGLState *gls, | |
127 | DisplaySurface *surface) | |
128 | { | |
129 | assert(gls); | |
130 | ||
131 | glClearColor(0.1f, 0.1f, 0.1f, 0.0f); | |
132 | glClear(GL_COLOR_BUFFER_BIT); | |
133 | ||
134 | qemu_gl_run_texture_blit(gls->texture_blit_prog); | |
135 | } | |
136 | ||
137 | void surface_gl_destroy_texture(ConsoleGLState *gls, | |
138 | DisplaySurface *surface) | |
139 | { | |
140 | if (!surface || !surface->texture) { | |
141 | return; | |
142 | } | |
143 | glDeleteTextures(1, &surface->texture); | |
144 | surface->texture = 0; | |
145 | } | |
146 | ||
147 | void surface_gl_setup_viewport(ConsoleGLState *gls, | |
148 | DisplaySurface *surface, | |
149 | int ww, int wh) | |
150 | { | |
151 | int gw, gh, stripe; | |
152 | float sw, sh; | |
153 | ||
154 | assert(gls); | |
155 | ||
156 | gw = surface_width(surface); | |
157 | gh = surface_height(surface); | |
158 | ||
159 | sw = (float)ww/gw; | |
160 | sh = (float)wh/gh; | |
161 | if (sw < sh) { | |
162 | stripe = wh - wh*sw/sh; | |
163 | glViewport(0, stripe / 2, ww, wh - stripe); | |
164 | } else { | |
165 | stripe = ww - ww*sh/sw; | |
166 | glViewport(stripe / 2, 0, ww - stripe, wh); | |
167 | } | |
168 | } |