From b97da19828ea2fcd49f41a53eb48e7b888dc8760 Mon Sep 17 00:00:00 2001 From: jp9000 Date: Wed, 2 Oct 2013 00:59:06 -0700 Subject: [PATCH] add GL initialization code for windows (so I can have something to test more easily with) --- libobs-opengl/gl-exports.h | 179 ++++++++++++++++++++++++++++ libobs-opengl/gl-subsystem.h | 9 +- libobs-opengl/gl-windows.c | 222 +++++++++++++++++++++++++++++++++++ 3 files changed, 409 insertions(+), 1 deletion(-) create mode 100644 libobs-opengl/gl-exports.h create mode 100644 libobs-opengl/gl-windows.c diff --git a/libobs-opengl/gl-exports.h b/libobs-opengl/gl-exports.h new file mode 100644 index 000000000..100e9868d --- /dev/null +++ b/libobs-opengl/gl-exports.h @@ -0,0 +1,179 @@ +#ifndef GS_GLEXPORTS +#define GS_GLEXPORTS + +#include "util/c99defs.h" + +EXPORT device_t device_create(struct gs_init_data *data); +EXPORT void device_destroy(device_t device); +EXPORT swapchain_t device_create_swapchain(device_t device, + struct gs_init_data *data); +EXPORT void device_resize(device_t device, uint32_t x, uint32_t y); +EXPORT void device_getsize(device_t device, uint32_t *x, uint32_t *y); +EXPORT uint32_t device_getwidth(device_t device); +EXPORT uint32_t device_getheight(device_t device); +EXPORT texture_t device_create_texture(device_t device, uint32_t width, + uint32_t height, enum gs_color_format color_format, void *data, + uint32_t flags); +EXPORT texture_t device_create_cubetexture(device_t device, uint32_t size, + enum gs_color_format color_format, void *data[6], + uint32_t flags); +EXPORT texture_t device_create_volumetexture(device_t device, uint32_t width, + uint32_t height, uint32_t depth, + enum gs_color_format color_format, void *data, uint32_t flags); +EXPORT zstencil_t device_create_zstencil(device_t device, uint32_t width, + uint32_t height, enum gs_zstencil_format format); +EXPORT stagesurf_t device_create_stagesurface(device_t device, uint32_t width, + uint32_t height, enum gs_color_format color_format); +EXPORT samplerstate_t device_create_samplerstate(device_t device, + struct gs_sampler_info *info); +EXPORT shader_t device_create_vertexshader(device_t device, + const char *shader, const char *file, + char **error_string); +EXPORT shader_t device_create_pixelshader(device_t device, + const char *shader, const char *file, + char **error_string); +EXPORT vertbuffer_t device_create_vertexbuffer(device_t device, + struct vb_data *data, uint32_t flags); +EXPORT indexbuffer_t device_create_indexbuffer(device_t device, + enum gs_index_type type, void *indices, size_t num, + uint32_t flags); +EXPORT enum gs_texture_type device_gettexturetype(device_t device, + texture_t texture); +EXPORT void device_load_vertexbuffer(device_t device, vertbuffer_t vertbuffer); +EXPORT void device_load_indexbuffer(device_t device, indexbuffer_t indexbuffer); +EXPORT void device_load_texture(device_t device, texture_t tex, int unit); +EXPORT void device_load_cubetexture(device_t device, texture_t cubetex, + int unit); +EXPORT void device_load_volumetexture(device_t device, texture_t voltex, + int unit); +EXPORT void device_load_samplerstate(device_t device, + samplerstate_t samplerstate, int unit); +EXPORT void device_load_vertexshader(device_t device, shader_t vertshader); +EXPORT void device_load_pixelshader(device_t device, shader_t pixelshader); +EXPORT void device_load_defaultsamplerstate(device_t device, bool b_3d, + int unit); +EXPORT shader_t device_getvertexshader(device_t device); +EXPORT shader_t device_getpixelshader(device_t device); +EXPORT texture_t device_getrendertarget(device_t device); +EXPORT zstencil_t device_getzstenciltarget(device_t device); +EXPORT void device_setrendertarget(device_t device, texture_t tex, + zstencil_t zstencil); +EXPORT void device_setcuberendertarget(device_t device, texture_t cubetex, + int side, zstencil_t zstencil); +EXPORT void device_copy_texture(device_t device, texture_t dst, texture_t src); +EXPORT void device_stage_texture(device_t device, stagesurf_t dst, + texture_t src); +EXPORT void device_beginscene(device_t device); +EXPORT void device_draw(device_t device, enum gs_draw_mode draw_mode, + uint32_t start_vert, uint32_t num_verts); +EXPORT void device_endscene(device_t device); +EXPORT void device_load_swapchain(device_t device, swapchain_t swapchain); +EXPORT void device_clear(device_t device, uint32_t clear_flags, + struct vec4 *color, float depth, uint8_t stencil); +EXPORT void device_present(device_t device); +EXPORT void device_setcullmode(device_t device, enum gs_cull_mode mode); +EXPORT enum gs_cull_mode device_getcullmode(device_t device); +EXPORT void device_enable_blending(device_t device, bool enable); +EXPORT void device_enable_depthtest(device_t device, bool enable); +EXPORT void device_enable_stenciltest(device_t device, bool enable); +EXPORT void device_enable_stencilwrite(device_t device, bool enable); +EXPORT void device_enable_color(device_t device, bool red, bool blue, + bool green, bool alpha); +EXPORT void device_blendfunction(device_t device, enum gs_blend_type src, + enum gs_blend_type dest); +EXPORT void device_depthfunction(device_t device, enum gs_depth_test test); +EXPORT void device_stencilfunction(device_t device, enum gs_stencil_side side, + enum gs_depth_test test); +EXPORT void device_stencilop(device_t device, enum gs_stencil_side side, + enum gs_stencil_op fail, enum gs_stencil_op zfail, + enum gs_stencil_op zpass); +EXPORT void device_enable_fullscreen(device_t device, bool enable); +EXPORT int device_fullscreen_enabled(device_t device); +EXPORT void device_setdisplaymode(device_t device, + const struct gs_display_mode *mode); +EXPORT void device_getdisplaymode(device_t device, + struct gs_display_mode *mode); +EXPORT void device_setcolorramp(device_t device, float gamma, float brightness, + float contrast); +EXPORT void device_setviewport(device_t device, int x, int y, int width, + int height); +EXPORT void device_getviewport(device_t device, struct gs_rect *rect); +EXPORT void device_setscissorrect(device_t device, struct gs_rect *rect); +EXPORT void device_ortho(device_t device, float left, float right, + float top, float bottom, float znear, float zfar); +EXPORT void device_frustum(device_t device, float left, float right, + float top, float bottom, float znear, float zfar); +EXPORT void device_perspective(device_t device, float fovy, float aspect, + float znear, float zfar); +EXPORT void device_set_view_matrix(device_t device, struct matrix3 *mat); +EXPORT void device_projection_push(device_t device); +EXPORT void device_projection_pop(device_t device); + +EXPORT void swapchain_destroy(swapchain_t swapchain); + +EXPORT void texture_destroy(texture_t tex); +EXPORT uint32_t texture_getwidth(texture_t tex); +EXPORT uint32_t texture_getheight(texture_t tex); +EXPORT enum gs_color_format texture_getcolorformat(texture_t tex); +EXPORT bool texture_map(texture_t tex, void **ptr, uint32_t *byte_width); +EXPORT void texture_unmap(texture_t tex); + +EXPORT void cubetexture_destroy(texture_t cubetex); +EXPORT uint32_t cubetexture_getsize(texture_t cubetex); +EXPORT enum gs_color_format cubetexture_getcolorformat(texture_t cubetex); + +EXPORT void volumetexture_destroy(texture_t voltex); +EXPORT uint32_t volumetexture_getwidth(texture_t voltex); +EXPORT uint32_t volumetexture_getheight(texture_t voltex); +EXPORT uint32_t volumetexture_getdepth(texture_t voltex); +EXPORT enum gs_color_format volumetexture_getcolorformat(texture_t voltex); + +EXPORT void stagesurface_destroy(stagesurf_t stagesurf); +EXPORT uint32_t stagesurface_getwidth(stagesurf_t stagesurf); +EXPORT uint32_t stagesurface_getheight(stagesurf_t stagesurf); +EXPORT enum gs_color_format stagesurface_getcolorformat(stagesurf_t stagesurf); +EXPORT bool stagesurface_map(stagesurf_t stagesurf, const void **data, + uint32_t *byte_width); +EXPORT void stagesurface_unmap(stagesurf_t stagesurf); + +EXPORT void zstencil_destroy(zstencil_t zstencil); + +EXPORT void samplerstate_destroy(samplerstate_t samplerstate); + +EXPORT void vertexbuffer_destroy(vertbuffer_t vertbuffer); +EXPORT void vertexbuffer_flush(vertbuffer_t vertbuffer, bool rebuild); +EXPORT struct vb_data *vertexbuffer_getdata(vertbuffer_t vertbuffer); + +EXPORT void indexbuffer_destroy(indexbuffer_t indexbuffer); +EXPORT void indexbuffer_flush(indexbuffer_t indexbuffer); +EXPORT void *indexbuffer_getdata(indexbuffer_t indexbuffer); +EXPORT size_t indexbuffer_numindices(indexbuffer_t indexbuffer); +EXPORT enum gs_index_type indexbuffer_gettype(indexbuffer_t indexbuffer); + +EXPORT void shader_destroy(shader_t shader); +EXPORT int shader_numparams(shader_t shader); +EXPORT sparam_t shader_getparambyidx(shader_t shader, int param); +EXPORT sparam_t shader_getparambyname(shader_t shader, const char *name); +EXPORT void shader_getparaminfo(shader_t shader, sparam_t param, + struct shader_param_info *info); +EXPORT sparam_t shader_getviewprojmatrix(shader_t shader); +EXPORT sparam_t shader_getworldmatrix(shader_t shader); +EXPORT void shader_setbool(shader_t shader, sparam_t param, bool val); +EXPORT void shader_setfloat(shader_t shader, sparam_t param, float val); +EXPORT void shader_setint(shader_t shader, sparam_t param, int val); +EXPORT void shader_setmatrix3(shader_t shader, sparam_t param, + const struct matrix3 *val); +EXPORT void shader_setmatrix4(shader_t shader, sparam_t param, + const struct matrix4 *val); +EXPORT void shader_setvec2(shader_t shader, sparam_t param, + const struct vec2 *val); +EXPORT void shader_setvec3(shader_t shader, sparam_t param, + const struct vec3 *val); +EXPORT void shader_setvec4(shader_t shader, sparam_t param, + const struct vec4 *val); +EXPORT void shader_settexture(shader_t shader, sparam_t param, texture_t val); +EXPORT void shader_setval(shader_t shader, sparam_t param, const void *val, + size_t size); +EXPORT void shader_setdefault(shader_t shader, sparam_t param); + +#endif diff --git a/libobs-opengl/gl-subsystem.h b/libobs-opengl/gl-subsystem.h index a226b31b1..282e5232f 100644 --- a/libobs-opengl/gl-subsystem.h +++ b/libobs-opengl/gl-subsystem.h @@ -18,6 +18,13 @@ #ifndef GL_SUBSYSTEM_H #define GL_SUBSYSTEM_H -#include "glew.h" +#include "graphics/graphics.h" +#include "glew/include/GL/glew.h" + +struct gl_platform; + +struct gs_device { + struct gl_platform *plat; +}; #endif diff --git a/libobs-opengl/gl-windows.c b/libobs-opengl/gl-windows.c new file mode 100644 index 000000000..4dbff992a --- /dev/null +++ b/libobs-opengl/gl-windows.c @@ -0,0 +1,222 @@ +#define WIN32_LEAN_AND_MEAN +#include + +#include "util/darray.h" +#include "gl-subsystem.h" +#include "glew/include/GL/wglew.h" + +struct gl_platform { + HDC hdc; + HGLRC hrc; +}; + +struct gl_window { + HDC hdc; +}; + +/* would use designated initializers but microsoft sort of sucks */ +static inline void init_dummy_pixel_format(PIXELFORMATDESCRIPTOR *pfd) +{ + memset(&pfd, 0, sizeof(pfd)); + pfd->nSize = sizeof(pfd); + pfd->nVersion = 1; + pfd->iPixelType = PFD_TYPE_RGBA; + pfd->cColorBits = 32; + pfd->cDepthBits = 24; + pfd->cStencilBits = 8; + pfd->iLayerType = PFD_MAIN_PLANE; + pfd->dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | + PFD_DOUBLEBUFFER; +} + +static bool gl_create_false_context(struct gl_platform *plat, + struct gs_init_data *info) +{ + PIXELFORMATDESCRIPTOR pfd; + int format_index; + + plat->hdc = GetDC(info->hwnd); + + init_dummy_pixel_format(&pfd); + + format_index = ChoosePixelFormat(plat->hdc, &pfd); + if (!format_index) { + blog(LOG_ERROR, "ChoosePixelFormat failed, %u", GetLastError()); + return false; + } + + if (!SetPixelFormat(plat->hdc, format_index, &pfd)) { + blog(LOG_ERROR, "SetPixelFormat failed, %u", GetLastError()); + return false; + } + + plat->hrc = wglCreateContext(plat->hdc); + if (!plat->hrc) { + blog(LOG_ERROR, "wglCreateContext failed, %u", GetLastError()); + return false; + } + + if (!wglMakeCurrent(plat->hdc, plat->hrc)) { + blog(LOG_ERROR, "wglMakeCurrent failed, %u", GetLastError()); + return false; + } + + return true; +} + +static inline void required_extension_error(const char *extension) +{ + blog(LOG_ERROR, "OpenGL extension %s is required", extension); +} + +static bool gl_init_extensions(void) +{ + GLenum errorcode = glewInit(); + if (errorcode != GLEW_OK) { + blog(LOG_ERROR, "glewInit failed, %u", errorcode); + return false; + } + + if (!GLEW_VERSION_2_1) { + blog(LOG_ERROR, "OpenGL 2.1 minimum required by the graphics " + "adapter"); + return false; + } + + if (!GLEW_ARB_framebuffer_object) { + required_extension_error("GL_ARB_framebuffer_object"); + return false; + } + + if (!WGLEW_EXT_swap_control) { + required_extension_error("WGL_EXT_swap_control"); + return false; + } + + if (!WGLEW_ARB_pixel_format) { + required_extension_error("WGL_ARB_pixel_format"); + return false; + } + + return true; +} + +static inline int get_color_format_bits(enum gs_color_format format) +{ + switch (format) { + case GS_RGBA: + return 32; + default: + return 0; + } +} + +static inline int get_depth_format_bits(enum gs_zstencil_format zsformat) +{ + switch (zsformat) { + case GS_Z16: + return 16; + case GS_Z24_S8: + return 24; + default: + return 0; + } +} + +static inline int get_stencil_format_bits(enum gs_zstencil_format zsformat) +{ + switch (zsformat) { + case GS_Z24_S8: + return 8; + default: + return 0; + } +} + +static inline void add_attrib(struct darray *list, int attrib, int val) +{ + darray_push_back(sizeof(int), list, &attrib); + darray_push_back(sizeof(int), list, &val); +} + +static int gl_get_pixel_format(struct gl_platform *plat, + struct gs_init_data *info) +{ + struct darray attribs; + int color_bits = get_color_format_bits(info->format); + int depth_bits = get_depth_format_bits(info->zsformat); + int stencil_bits = get_stencil_format_bits(info->zsformat); + UINT num_formats; + int format; + + if (!color_bits) { + blog(LOG_ERROR, "gl_init_pixel_format: color format not " + "supported"); + return false; + } + + darray_init(&attribs); + add_attrib(&attribs, WGL_DRAW_TO_WINDOW_ARB, GL_TRUE); + add_attrib(&attribs, WGL_SUPPORT_OPENGL_ARB, GL_TRUE); + add_attrib(&attribs, WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB); + add_attrib(&attribs, WGL_DOUBLE_BUFFER_ARB, GL_TRUE); + add_attrib(&attribs, WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB); + add_attrib(&attribs, WGL_COLOR_BITS_ARB, color_bits); + add_attrib(&attribs, WGL_DEPTH_BITS_ARB, depth_bits); + add_attrib(&attribs, WGL_STENCIL_BITS_ARB, stencil_bits); + add_attrib(&attribs, 0, 0); + + if (!wglChoosePixelFormatARB(plat->hdc, attribs.array, NULL, 1, + &format, &num_formats)) { + blog(LOG_ERROR, "wglChoosePixelFormatARB failed, %u", + GetLastError()); + format = 0; + } + + darray_free(&attribs); + + return format; +} + +static inline bool gl_init_pixel_format(struct gl_platform *plat, + struct gs_init_data *info) +{ + PIXELFORMATDESCRIPTOR pfd; + int format = gl_get_pixel_format(plat, info); + + if (!format) + return false; + + if (!DescribePixelFormat(plat->hdc, format, sizeof(pfd), &pfd)) { + blog(LOG_ERROR, "DescribePixelFormat failed, %u", + GetLastError()); + return false; + } + + if (!SetPixelFormat(plat->hdc, format, &pfd)) { + blog(LOG_ERROR, "SetPixelFormat failed, %u", GetLastError()); + return false; + } + + return true; +} + +bool gl_platform_init(struct gs_device *device, struct gs_init_data *info) +{ + device->plat = bmalloc(sizeof(struct gl_platform)); + memset(device->plat, 0, sizeof(struct gl_platform)); + + if (!gl_create_false_context(device->plat, info)) + goto fail; + + if (!gl_init_extensions()) + goto fail; + + if (!gl_init_pixel_format(device->plat, info)) + goto fail; + + return true; + +fail: + return false; +}