diff --git a/CMakeLists.txt b/CMakeLists.txt index 37e4f14f5e..15cd489dd3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -218,6 +218,12 @@ if(FASTLOG) add_definitions(-DDEBUGFAST) endif() +option(USE_GLES "Enables GLES, disables OGL" OFF) +if(USE_GLES) + message("GLES rendering enabled") + add_definitions(-DUSE_GLES) + add_definitions(-DUSE_EGL) +endif() add_definitions(-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE) ######################################## diff --git a/Source/Core/Common/Src/VideoBackendBase.cpp b/Source/Core/Common/Src/VideoBackendBase.cpp index 339cb016c1..d0ec7819bc 100644 --- a/Source/Core/Common/Src/VideoBackendBase.cpp +++ b/Source/Core/Common/Src/VideoBackendBase.cpp @@ -22,7 +22,9 @@ #include "../../../Plugins/Plugin_VideoDX9/Src/VideoBackend.h" #include "../../../Plugins/Plugin_VideoDX11/Src/VideoBackend.h" #endif +#ifndef USE_GLES #include "../../../Plugins/Plugin_VideoOGL/Src/VideoBackend.h" +#endif #include "../../../Plugins/Plugin_VideoSoftware/Src/VideoBackend.h" std::vector g_available_video_backends; @@ -52,7 +54,9 @@ void VideoBackend::PopulateList() if (IsGteVista()) g_available_video_backends.push_back(new DX11::VideoBackend); #endif +#ifndef USE_GLES g_available_video_backends.push_back(new OGL::VideoBackend); +#endif g_available_video_backends.push_back(new SW::VideoSoftware); g_video_backend = g_available_video_backends.front(); diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index d11c4a350a..47276dd172 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -191,7 +191,11 @@ set(SRCS Src/ActionReplay.cpp Src/PowerPC/JitCommon/JitCache.cpp Src/PowerPC/JitCommon/Jit_Util.cpp) -set(LIBS bdisasm inputcommon videoogl videosoftware sfml-network) +set(LIBS bdisasm inputcommon videosoftware sfml-network) + +if(NOT USE_GLES) + set(LIBS ${LIBS} videoogl) +endif() if(WIN32) set(SRCS ${SRCS} Src/HW/BBA-TAP/TAP_Win32.cpp Src/stdafx.cpp diff --git a/Source/Core/DolphinWX/CMakeLists.txt b/Source/Core/DolphinWX/CMakeLists.txt index d03cf7c6b1..fcc531029c 100644 --- a/Source/Core/DolphinWX/CMakeLists.txt +++ b/Source/Core/DolphinWX/CMakeLists.txt @@ -8,7 +8,6 @@ set(LIBS core z sfml-network ${GTK2_LIBRARIES} - ${OPENGL_LIBRARIES} ${XRANDR_LIBRARIES} ${X11_LIBRARIES}) @@ -31,7 +30,8 @@ if(LIBAV_FOUND) endif() if(wxWidgets_FOUND) - set(SRCS Src/ARCodeAddEdit.cpp + set(SRCS + Src/ARCodeAddEdit.cpp Src/AboutDolphin.cpp Src/CheatsWindow.cpp Src/ConfigMain.cpp @@ -79,7 +79,28 @@ if(wxWidgets_FOUND) set(WXLIBS ${wxWidgets_LIBRARIES}) else() - set(SRCS Src/MainNoGUI.cpp) + set(SRCS + Src/MainNoGUI.cpp) +endif() + +if(USE_EGL) + set(SRCS ${SRCS} + Src/VideoInterface/EGL.cpp + ) +else() + if(WIN32) + set(SRCS ${SRCS} + Src/VideoInterface/GLW.cpp + ) + elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(SRCS ${SRCS} + Src/VideoInterface/AGL.cpp + ) + else() + set(SRCS ${SRCS} + Src/VideoInterface/GLX.cpp + ) + endif() endif() if(WIN32) diff --git a/Source/Plugins/CMakeLists.txt b/Source/Plugins/CMakeLists.txt index 0a0412377a..7dfdbaca83 100644 --- a/Source/Plugins/CMakeLists.txt +++ b/Source/Plugins/CMakeLists.txt @@ -1,3 +1,5 @@ -add_subdirectory(Plugin_VideoOGL) +if(NOT USE_GLES) + add_subdirectory(Plugin_VideoOGL) +endif() add_subdirectory(Plugin_VideoSoftware) # TODO: Add other backends here! diff --git a/Source/Plugins/Plugin_VideoOGL/CMakeLists.txt b/Source/Plugins/Plugin_VideoOGL/CMakeLists.txt index b506087106..43b127f5ef 100644 --- a/Source/Plugins/Plugin_VideoOGL/CMakeLists.txt +++ b/Source/Plugins/Plugin_VideoOGL/CMakeLists.txt @@ -12,11 +12,22 @@ set(SRCS Src/FramebufferManager.cpp Src/VertexManager.cpp) set(LIBS videocommon - GLEW SOIL common - ${OPENGL_LIBRARIES} ${X11_LIBRARIES}) +if(USE_EGL) + set(LIBS ${LIBS} + EGL) +endif() + +if(USE_GLES) + set(LIBS ${LIBS} + GLESv2) +else() + set(LIBS ${LIBS} + GLEW + ${OPENGL_LIBRARIES}) +endif() if(wxWidgets_FOUND) set(LIBS ${LIBS} ${wxWidgets_LIBRARIES}) diff --git a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp index d6abb014c4..17986a4921 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp @@ -28,59 +28,8 @@ #include "GLUtil.h" -#if defined(_WIN32) -#include "EmuWindow.h" -static HDC hDC = NULL; // Private GDI Device Context -static HGLRC hRC = NULL; // Permanent Rendering Context -#else GLWindow GLWin; -#endif - -// Handles OpenGL and the window - -// Window dimensions. -static int s_backbuffer_width; -static int s_backbuffer_height; - -void OpenGL_SwapBuffers() -{ -#if defined(USE_WX) && USE_WX - GLWin.glCanvas->SwapBuffers(); -#elif defined(__APPLE__) - [GLWin.cocoaCtx flushBuffer]; -#elif defined(_WIN32) - SwapBuffers(hDC); -#elif defined(HAVE_X11) && HAVE_X11 - glXSwapBuffers(GLWin.dpy, GLWin.win); -#endif -} - -u32 OpenGL_GetBackbufferWidth() -{ - return s_backbuffer_width; -} - -u32 OpenGL_GetBackbufferHeight() -{ - return s_backbuffer_height; -} - -void OpenGL_SetWindowText(const char *text) -{ -#if defined(USE_WX) && USE_WX - // Handled by Host_UpdateTitle() -#elif defined(__APPLE__) - [GLWin.cocoaWin setTitle: [NSString stringWithUTF8String: text]]; -#elif defined(_WIN32) - TCHAR temp[512]; - swprintf_s(temp, sizeof(temp)/sizeof(TCHAR), _T("%hs"), text); - EmuWindow::SetWindowText(temp); -#elif defined(HAVE_X11) && HAVE_X11 - // Tell X to ask the window manager to set the window title. - // (X itself doesn't provide window title functionality.) - XStoreName(GLWin.dpy, GLWin.win, text); -#endif -} +cInterfaceBase *GLInterface; namespace OGL { @@ -88,20 +37,7 @@ namespace OGL // Draw messages on top of the screen unsigned int VideoBackend::PeekMessages() { -#ifdef _WIN32 - // TODO: peekmessage - MSG msg; - while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) - { - if (msg.message == WM_QUIT) - return FALSE; - TranslateMessage(&msg); - DispatchMessage(&msg); - } - return TRUE; -#else - return false; -#endif + return GLInterface->PeekMessages(); } // Show the current FPS @@ -109,523 +45,86 @@ void VideoBackend::UpdateFPSDisplay(const char *text) { char temp[100]; snprintf(temp, sizeof temp, "%s | OpenGL | %s", scm_rev_str, text); - OpenGL_SetWindowText(temp); + return GLInterface->UpdateFPSDisplay(temp); } } - -#if defined(HAVE_X11) && HAVE_X11 -void XEventThread(); - -void CreateXWindow(void) +void InitInterface() { - Atom wmProtocols[1]; - - // Setup window attributes - GLWin.attr.colormap = XCreateColormap(GLWin.evdpy, - GLWin.parent, GLWin.vi->visual, AllocNone); - GLWin.attr.event_mask = KeyPressMask | StructureNotifyMask | FocusChangeMask; - GLWin.attr.background_pixel = BlackPixel(GLWin.evdpy, GLWin.screen); - GLWin.attr.border_pixel = 0; - - // Create the window - GLWin.win = XCreateWindow(GLWin.evdpy, GLWin.parent, - GLWin.x, GLWin.y, GLWin.width, GLWin.height, 0, - GLWin.vi->depth, InputOutput, GLWin.vi->visual, - CWBorderPixel | CWBackPixel | CWColormap | CWEventMask, &GLWin.attr); - wmProtocols[0] = XInternAtom(GLWin.evdpy, "WM_DELETE_WINDOW", True); - XSetWMProtocols(GLWin.evdpy, GLWin.win, wmProtocols, 1); - XSetStandardProperties(GLWin.evdpy, GLWin.win, "GPU", "GPU", None, NULL, 0, NULL); - XMapRaised(GLWin.evdpy, GLWin.win); - XSync(GLWin.evdpy, True); - - GLWin.xEventThread = std::thread(XEventThread); + #if defined(USE_EGL) && USE_EGL + GLInterface = new cInterfaceEGL; + #elif defined(USE_WX) && USE_WX + GLInterface = new cInterfaceWX; + #elif defined(__APPLE__) + GLInterface = new cInterfaceAGL; + #elif defined(_WIN32) + GLInterface = new cInterfaceWGL; + #elif defined(HAVE_X11) && HAVE_X11 + GLInterface = new cInterfaceGLX; + #endif } -void DestroyXWindow(void) +GLuint OpenGL_CompileProgram ( const char* vertexShader, const char* fragmentShader ) { - XUnmapWindow(GLWin.dpy, GLWin.win); - GLWin.win = 0; - if (GLWin.xEventThread.joinable()) - GLWin.xEventThread.join(); - XFreeColormap(GLWin.evdpy, GLWin.attr.colormap); -} - -void XEventThread() -{ - // Free look variables - static bool mouseLookEnabled = false; - static bool mouseMoveEnabled = false; - static float lastMouse[2]; - while (GLWin.win) - { - XEvent event; - KeySym key; - for (int num_events = XPending(GLWin.evdpy); num_events > 0; num_events--) - { - XNextEvent(GLWin.evdpy, &event); - switch(event.type) { - case KeyPress: - key = XLookupKeysym((XKeyEvent*)&event, 0); - switch (key) - { - case XK_3: - OSDChoice = 1; - // Toggle native resolution - g_Config.iEFBScale = g_Config.iEFBScale + 1; - if (g_Config.iEFBScale > 7) g_Config.iEFBScale = 0; - break; - case XK_4: - OSDChoice = 2; - // Toggle aspect ratio - g_Config.iAspectRatio = (g_Config.iAspectRatio + 1) & 3; - break; - case XK_5: - OSDChoice = 3; - // Toggle EFB copy - if (!g_Config.bEFBCopyEnable || g_Config.bCopyEFBToTexture) - { - g_Config.bEFBCopyEnable ^= true; - g_Config.bCopyEFBToTexture = false; - } - else - { - g_Config.bCopyEFBToTexture = !g_Config.bCopyEFBToTexture; - } - break; - case XK_6: - OSDChoice = 4; - g_Config.bDisableFog = !g_Config.bDisableFog; - break; - default: - break; - } - if (g_Config.bFreeLook) - { - static float debugSpeed = 1.0f; - switch (key) - { - case XK_parenleft: - debugSpeed /= 2.0f; - break; - case XK_parenright: - debugSpeed *= 2.0f; - break; - case XK_w: - VertexShaderManager::TranslateView(0.0f, debugSpeed); - break; - case XK_s: - VertexShaderManager::TranslateView(0.0f, -debugSpeed); - break; - case XK_a: - VertexShaderManager::TranslateView(debugSpeed, 0.0f); - break; - case XK_d: - VertexShaderManager::TranslateView(-debugSpeed, 0.0f); - break; - case XK_r: - VertexShaderManager::ResetView(); - break; - } - } - break; - case ButtonPress: - if (g_Config.bFreeLook) - { - switch (event.xbutton.button) - { - case 2: // Middle button - lastMouse[0] = event.xbutton.x; - lastMouse[1] = event.xbutton.y; - mouseMoveEnabled = true; - break; - case 3: // Right button - lastMouse[0] = event.xbutton.x; - lastMouse[1] = event.xbutton.y; - mouseLookEnabled = true; - break; - } - } - break; - case ButtonRelease: - if (g_Config.bFreeLook) - { - switch (event.xbutton.button) - { - case 2: // Middle button - mouseMoveEnabled = false; - break; - case 3: // Right button - mouseLookEnabled = false; - break; - } - } - break; - case MotionNotify: - if (g_Config.bFreeLook) - { - if (mouseLookEnabled) - { - VertexShaderManager::RotateView((event.xmotion.x - lastMouse[0]) / 200.0f, - (event.xmotion.y - lastMouse[1]) / 200.0f); - lastMouse[0] = event.xmotion.x; - lastMouse[1] = event.xmotion.y; - } - - if (mouseMoveEnabled) - { - VertexShaderManager::TranslateView((event.xmotion.x - lastMouse[0]) / 50.0f, - (event.xmotion.y - lastMouse[1]) / 50.0f); - lastMouse[0] = event.xmotion.x; - lastMouse[1] = event.xmotion.y; - } - } - break; - case ConfigureNotify: - Window winDummy; - unsigned int borderDummy, depthDummy; - XGetGeometry(GLWin.evdpy, GLWin.win, &winDummy, &GLWin.x, &GLWin.y, - &GLWin.width, &GLWin.height, &borderDummy, &depthDummy); - s_backbuffer_width = GLWin.width; - s_backbuffer_height = GLWin.height; - break; - case ClientMessage: - if ((unsigned long) event.xclient.data.l[0] == - XInternAtom(GLWin.evdpy, "WM_DELETE_WINDOW", False)) - Host_Message(WM_USER_STOP); - if ((unsigned long) event.xclient.data.l[0] == - XInternAtom(GLWin.evdpy, "RESIZE", False)) - XMoveResizeWindow(GLWin.evdpy, GLWin.win, - event.xclient.data.l[1], event.xclient.data.l[2], - event.xclient.data.l[3], event.xclient.data.l[4]); - break; - default: - break; - } - } - Common::SleepCurrentThread(20); - } -} -#endif - -// Create rendering window. -// Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize() -bool OpenGL_Create(void *&window_handle) -{ - int _tx, _ty, _twidth, _theight; - Host_GetRenderWindowSize(_tx, _ty, _twidth, _theight); - - // Control window size and picture scaling - s_backbuffer_width = _twidth; - s_backbuffer_height = _theight; - -#if defined(USE_WX) && USE_WX - GLWin.panel = (wxPanel *)window_handle; - GLWin.glCanvas = new wxGLCanvas(GLWin.panel, wxID_ANY, NULL, - wxPoint(0, 0), wxSize(_twidth, _theight)); - GLWin.glCanvas->Show(true); - if (GLWin.glCtxt == NULL) // XXX dirty hack - GLWin.glCtxt = new wxGLContext(GLWin.glCanvas); - -#elif defined(__APPLE__) - NSRect size; - NSUInteger style = NSMiniaturizableWindowMask; - NSOpenGLPixelFormatAttribute attr[2] = { NSOpenGLPFADoubleBuffer, 0 }; - NSOpenGLPixelFormat *fmt = [[NSOpenGLPixelFormat alloc] - initWithAttributes: attr]; - if (fmt == nil) { - ERROR_LOG(VIDEO, "failed to create pixel format"); - return NULL; - } - - GLWin.cocoaCtx = [[NSOpenGLContext alloc] - initWithFormat: fmt shareContext: nil]; - [fmt release]; - if (GLWin.cocoaCtx == nil) { - ERROR_LOG(VIDEO, "failed to create context"); - return NULL; - } - - if (SConfig::GetInstance().m_LocalCoreStartupParameter.bFullscreen) { - size = [[NSScreen mainScreen] frame]; - style |= NSBorderlessWindowMask; - } else { - size = NSMakeRect(_tx, _ty, _twidth, _theight); - style |= NSResizableWindowMask | NSTitledWindowMask; - } - - GLWin.cocoaWin = [[NSWindow alloc] initWithContentRect: size - styleMask: style backing: NSBackingStoreBuffered defer: NO]; - if (GLWin.cocoaWin == nil) { - ERROR_LOG(VIDEO, "failed to create window"); - return NULL; - } - - if (SConfig::GetInstance().m_LocalCoreStartupParameter.bFullscreen) { - CGDisplayCapture(CGMainDisplayID()); - [GLWin.cocoaWin setLevel: CGShieldingWindowLevel()]; - } - - [GLWin.cocoaCtx setView: [GLWin.cocoaWin contentView]]; - [GLWin.cocoaWin makeKeyAndOrderFront: nil]; - -#elif defined(_WIN32) - window_handle = (void*)EmuWindow::Create((HWND)window_handle, GetModuleHandle(0), _T("Please wait...")); - if (window_handle == NULL) - { - Host_SysMessage("failed to create window"); - return false; - } - - // Show the window - EmuWindow::Show(); - - PIXELFORMATDESCRIPTOR pfd = // pfd Tells Windows How We Want Things To Be - { - sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor - 1, // Version Number - PFD_DRAW_TO_WINDOW | // Format Must Support Window - PFD_SUPPORT_OPENGL | // Format Must Support OpenGL - PFD_DOUBLEBUFFER, // Must Support Double Buffering - PFD_TYPE_RGBA, // Request An RGBA Format - 32, // Select Our Color Depth - 0, 0, 0, 0, 0, 0, // Color Bits Ignored - 0, // 8bit Alpha Buffer - 0, // Shift Bit Ignored - 0, // No Accumulation Buffer - 0, 0, 0, 0, // Accumulation Bits Ignored - 24, // 24Bit Z-Buffer (Depth Buffer) - 8, // 8bit Stencil Buffer - 0, // No Auxiliary Buffer - PFD_MAIN_PLANE, // Main Drawing Layer - 0, // Reserved - 0, 0, 0 // Layer Masks Ignored - }; - - GLuint PixelFormat; // Holds The Results After Searching For A Match - - if (!(hDC=GetDC(EmuWindow::GetWnd()))) { - PanicAlert("(1) Can't create an OpenGL Device context. Fail."); - return false; - } - if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd))) { - PanicAlert("(2) Can't find a suitable PixelFormat."); - return false; - } - if (!SetPixelFormat(hDC, PixelFormat, &pfd)) { - PanicAlert("(3) Can't set the PixelFormat."); - return false; - } - if (!(hRC = wglCreateContext(hDC))) { - PanicAlert("(4) Can't create an OpenGL rendering context."); - return false; - } - // -------------------------------------- - -#elif defined(HAVE_X11) && HAVE_X11 - int glxMajorVersion, glxMinorVersion; - - // attributes for a single buffered visual in RGBA format with at least - // 8 bits per color and a 24 bit depth buffer - int attrListSgl[] = {GLX_RGBA, GLX_RED_SIZE, 8, - GLX_GREEN_SIZE, 8, - GLX_BLUE_SIZE, 8, - GLX_DEPTH_SIZE, 24, - None}; - - // attributes for a double buffered visual in RGBA format with at least - // 8 bits per color and a 24 bit depth buffer - int attrListDbl[] = {GLX_RGBA, GLX_DOUBLEBUFFER, - GLX_RED_SIZE, 8, - GLX_GREEN_SIZE, 8, - GLX_BLUE_SIZE, 8, - GLX_DEPTH_SIZE, 24, - GLX_SAMPLE_BUFFERS_ARB, g_Config.iMultisampleMode != MULTISAMPLE_OFF?1:0, - GLX_SAMPLES_ARB, g_Config.iMultisampleMode != MULTISAMPLE_OFF?1:0, - None }; - - int attrListDefault[] = { - GLX_RGBA, - GLX_RED_SIZE, 1, - GLX_GREEN_SIZE, 1, - GLX_BLUE_SIZE, 1, - GLX_DOUBLEBUFFER, - GLX_DEPTH_SIZE, 1, - None }; - - GLWin.dpy = XOpenDisplay(0); - GLWin.evdpy = XOpenDisplay(0); - GLWin.parent = (Window)window_handle; - GLWin.screen = DefaultScreen(GLWin.dpy); - if (GLWin.parent == 0) - GLWin.parent = RootWindow(GLWin.dpy, GLWin.screen); - - glXQueryVersion(GLWin.dpy, &glxMajorVersion, &glxMinorVersion); - NOTICE_LOG(VIDEO, "glX-Version %d.%d", glxMajorVersion, glxMinorVersion); - - // Get an appropriate visual - GLWin.vi = glXChooseVisual(GLWin.dpy, GLWin.screen, attrListDbl); - if (GLWin.vi == NULL) - { - GLWin.vi = glXChooseVisual(GLWin.dpy, GLWin.screen, attrListSgl); - if (GLWin.vi != NULL) - { - ERROR_LOG(VIDEO, "Only single buffered visual!"); - } - else - { - GLWin.vi = glXChooseVisual(GLWin.dpy, GLWin.screen, attrListDefault); - if (GLWin.vi == NULL) - { - ERROR_LOG(VIDEO, "Could not choose visual (glXChooseVisual)"); - return false; - } - } - } - else - NOTICE_LOG(VIDEO, "Got double buffered visual!"); - - // Create a GLX context. - GLWin.ctx = glXCreateContext(GLWin.dpy, GLWin.vi, 0, GL_TRUE); - if (!GLWin.ctx) - { - PanicAlert("Unable to create GLX context."); - return false; - } - - GLWin.x = _tx; - GLWin.y = _ty; - GLWin.width = _twidth; - GLWin.height = _theight; - - CreateXWindow(); - window_handle = (void *)GLWin.win; -#endif - return true; -} - -bool OpenGL_MakeCurrent() -{ - // connect the glx-context to the window -#if defined(USE_WX) && USE_WX - return GLWin.glCanvas->SetCurrent(*GLWin.glCtxt); -#elif defined(__APPLE__) - [GLWin.cocoaCtx makeCurrentContext]; -#elif defined(_WIN32) - return wglMakeCurrent(hDC, hRC) ? true : false; -#elif defined(HAVE_X11) && HAVE_X11 -#if defined(HAVE_WX) && (HAVE_WX) - Host_GetRenderWindowSize(GLWin.x, GLWin.y, - (int&)GLWin.width, (int&)GLWin.height); - XMoveResizeWindow(GLWin.dpy, GLWin.win, GLWin.x, GLWin.y, - GLWin.width, GLWin.height); -#endif - return glXMakeCurrent(GLWin.dpy, GLWin.win, GLWin.ctx); -#endif - return true; -} - -// Update window width, size and etc. Called from Render.cpp -void OpenGL_Update() -{ -#if defined(USE_WX) && USE_WX - int width, height; - - GLWin.panel->GetSize(&width, &height); - if (width == s_backbuffer_width && height == s_backbuffer_height) - return; - - GLWin.glCanvas->SetFocus(); - GLWin.glCanvas->SetSize(0, 0, width, height); - GLWin.glCtxt->SetCurrent(*GLWin.glCanvas); - s_backbuffer_width = width; - s_backbuffer_height = height; - -#elif defined(__APPLE__) - int width, height; - - width = [[GLWin.cocoaWin contentView] frame].size.width; - height = [[GLWin.cocoaWin contentView] frame].size.height; - if (width == s_backbuffer_width && height == s_backbuffer_height) - return; - - [GLWin.cocoaCtx setView: [GLWin.cocoaWin contentView]]; - [GLWin.cocoaCtx update]; - [GLWin.cocoaCtx makeCurrentContext]; - s_backbuffer_width = width; - s_backbuffer_height = height; - -#elif defined(_WIN32) - RECT rcWindow; - if (!EmuWindow::GetParentWnd()) - { - // We are not rendering to a child window - use client size. - GetClientRect(EmuWindow::GetWnd(), &rcWindow); - } - else - { - // We are rendering to a child window - use parent size. - GetWindowRect(EmuWindow::GetParentWnd(), &rcWindow); - } - - // Get the new window width and height - // See below for documentation - int width = rcWindow.right - rcWindow.left; - int height = rcWindow.bottom - rcWindow.top; - - // If we are rendering to a child window - if (EmuWindow::GetParentWnd() != 0 && - (s_backbuffer_width != width || s_backbuffer_height != height) && - width >= 4 && height >= 4) - { - ::MoveWindow(EmuWindow::GetWnd(), 0, 0, width, height, FALSE); - s_backbuffer_width = width; - s_backbuffer_height = height; - } -#endif -} - -// Close backend -void OpenGL_Shutdown() -{ -#if defined(USE_WX) && USE_WX - GLWin.glCanvas->Hide(); - // XXX GLWin.glCanvas->Destroy(); - // XXX delete GLWin.glCtxt; -#elif defined(__APPLE__) - [GLWin.cocoaWin close]; - [GLWin.cocoaCtx clearDrawable]; - [GLWin.cocoaCtx release]; -#elif defined(_WIN32) - if (hRC) - { - if (!wglMakeCurrent(NULL, NULL)) - NOTICE_LOG(VIDEO, "Could not release drawing context."); - - if (!wglDeleteContext(hRC)) - ERROR_LOG(VIDEO, "Release Rendering Context Failed."); - - hRC = NULL; - } - - if (hDC && !ReleaseDC(EmuWindow::GetWnd(), hDC)) - { - ERROR_LOG(VIDEO, "Release Device Context Failed."); - hDC = NULL; - } + // generate objects + GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER); + GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER); + GLuint programID = glCreateProgram(); + GLint Result = GL_FALSE; + char stringBuffer[1024]; + GLsizei stringBufferUsage = 0; -#elif defined(HAVE_X11) && HAVE_X11 - DestroyXWindow(); - if (GLWin.ctx && !glXMakeCurrent(GLWin.dpy, None, NULL)) - NOTICE_LOG(VIDEO, "Could not release drawing context."); - if (GLWin.ctx) - { - glXDestroyContext(GLWin.dpy, GLWin.ctx); - XCloseDisplay(GLWin.dpy); - XCloseDisplay(GLWin.evdpy); - GLWin.ctx = NULL; + // compile vertex shader + glShaderSource(vertexShaderID, 1, &vertexShader, NULL); + glCompileShader(vertexShaderID); +#if defined(_DEBUG) || defined(DEBUGFAST) || defined(DEBUG_GLSL) + glGetShaderiv(vertexShaderID, GL_COMPILE_STATUS, &Result); + glGetShaderInfoLog(vertexShaderID, 1024, &stringBufferUsage, stringBuffer); + if(Result && stringBufferUsage) { + ERROR_LOG(VIDEO, "GLSL vertex shader warnings:\n%s%s", stringBuffer, vertexShader); + } else if(!Result) { + ERROR_LOG(VIDEO, "GLSL vertex shader error:\n%s%s", stringBuffer, vertexShader); + } else { + DEBUG_LOG(VIDEO, "GLSL vertex shader compiled:\n%s", vertexShader); + } + bool shader_errors = !Result; +#endif + + // compile fragment shader + glShaderSource(fragmentShaderID, 1, &fragmentShader, NULL); + glCompileShader(fragmentShaderID); +#if defined(_DEBUG) || defined(DEBUGFAST) || defined(DEBUG_GLSL) + glGetShaderiv(fragmentShaderID, GL_COMPILE_STATUS, &Result); + glGetShaderInfoLog(fragmentShaderID, 1024, &stringBufferUsage, stringBuffer); + if(Result && stringBufferUsage) { + ERROR_LOG(VIDEO, "GLSL fragment shader warnings:\n%s%s", stringBuffer, fragmentShader); + } else if(!Result) { + ERROR_LOG(VIDEO, "GLSL fragment shader error:\n%s%s", stringBuffer, fragmentShader); + } else { + DEBUG_LOG(VIDEO, "GLSL fragment shader compiled:\n%s", fragmentShader); + } + shader_errors |= !Result; +#endif + + // link them + glAttachShader(programID, vertexShaderID); + glAttachShader(programID, fragmentShaderID); + glLinkProgram(programID); +#if defined(_DEBUG) || defined(DEBUGFAST) || defined(DEBUG_GLSL) + glGetProgramiv(programID, GL_LINK_STATUS, &Result); + glGetProgramInfoLog(programID, 1024, &stringBufferUsage, stringBuffer); + if(Result && stringBufferUsage) { + ERROR_LOG(VIDEO, "GLSL linker warnings:\n%s%s%s", stringBuffer, vertexShader, fragmentShader); + } else if(!Result && !shader_errors) { + ERROR_LOG(VIDEO, "GLSL linker error:\n%s%s%s", stringBuffer, vertexShader, fragmentShader); } #endif + + // cleanup + glDeleteShader(vertexShaderID); + glDeleteShader(fragmentShaderID); + + return programID; } GLuint OpenGL_ReportGLError(const char *function, const char *file, int line) @@ -633,14 +132,15 @@ GLuint OpenGL_ReportGLError(const char *function, const char *file, int line) GLint err = glGetError(); if (err != GL_NO_ERROR) { - ERROR_LOG(VIDEO, "%s:%d: (%s) OpenGL error 0x%x - %s\n", - file, line, function, err, gluErrorString(err)); + ERROR_LOG(VIDEO, "%s:%d: (%s) OpenGL error 0x%x\n", + file, line, function, err); } return err; } void OpenGL_ReportARBProgramError() { +#ifndef USE_GLES const GLubyte* pstr = glGetString(GL_PROGRAM_ERROR_STRING_ARB); if (pstr != NULL && pstr[0] != 0) { @@ -650,10 +150,12 @@ void OpenGL_ReportARBProgramError() ERROR_LOG(VIDEO, "%s", (char*)pstr); ERROR_LOG(VIDEO, "\n"); } +#endif } bool OpenGL_ReportFBOError(const char *function, const char *file, int line) { +#ifndef USE_GLES unsigned int fbo_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); if (fbo_status != GL_FRAMEBUFFER_COMPLETE_EXT) { @@ -686,6 +188,7 @@ bool OpenGL_ReportFBOError(const char *function, const char *file, int line) file, line, function, error); return false; } +#endif return true; } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h index 23c31a1bb7..ae83401f38 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h @@ -20,26 +20,7 @@ #include "VideoConfig.h" #include "MathUtil.h" -#include "Thread.h" - -#ifdef _WIN32 -#define GLEW_STATIC -#include -#include -#elif defined HAVE_X11 && HAVE_X11 -#include -#include -#include -#include -#elif defined __APPLE__ -#include -#import -#endif - -#if defined USE_WX && USE_WX -#include "wx/wx.h" -#include "wx/glcanvas.h" -#endif +#include "GLVideoInterface.h" #ifndef GL_DEPTH24_STENCIL8_EXT // allows FBOs to support stencils #define GL_DEPTH_STENCIL_EXT 0x84F9 @@ -52,49 +33,11 @@ #include -typedef struct { -#if defined(USE_WX) && USE_WX - wxGLCanvas *glCanvas; - wxGLContext *glCtxt; - wxPanel *panel; -#elif defined(__APPLE__) - NSWindow *cocoaWin; - NSOpenGLContext *cocoaCtx; -#elif defined(HAVE_X11) && HAVE_X11 - int screen; - Window win; - Window parent; - // dpy used for glx stuff, evdpy for window events etc. - // evdpy is to be used by XEventThread only - Display *dpy, *evdpy; - XVisualInfo *vi; - GLXContext ctx; - XSetWindowAttributes attr; - std::thread xEventThread; - int x, y; - unsigned int width, height; #endif -} GLWindow; +void InitInterface(); -extern GLWindow GLWin; - -#endif - -// Public OpenGL util - -// Initialization / upkeep -bool OpenGL_Create(void *&); -void OpenGL_Shutdown(); -void OpenGL_Update(); -bool OpenGL_MakeCurrent(); -void OpenGL_SwapBuffers(); - -// Get status -u32 OpenGL_GetBackbufferWidth(); -u32 OpenGL_GetBackbufferHeight(); - -// Set things -void OpenGL_SetWindowText(const char *text); +// Helpers +GLuint OpenGL_CompileProgram(const char *vertexShader, const char *fragmentShader); // Error reporting - use the convenient macros. void OpenGL_ReportARBProgramError(); @@ -126,4 +69,7 @@ extern CGprofile g_cgvProf, g_cgfProf; // use GLSL shaders across the whole pipeline. Yikes! //#define USE_DUAL_SOURCE_BLEND +// TODO: should be removed if we use glsl a lot +#define DEBUG_GLSL + #endif // _GLINIT_H_ diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index 77bb91d48b..2c43100b4c 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -323,8 +323,8 @@ Renderer::Renderer() return; // TODO: fail // Decide frambuffer size - s_backbuffer_width = (int)OpenGL_GetBackbufferWidth(); - s_backbuffer_height = (int)OpenGL_GetBackbufferHeight(); + s_backbuffer_width = (int)GLInterface->GetBackBufferWidth(); + s_backbuffer_height = (int)GLInterface->GetBackBufferHeight(); // Handle VSync on/off #ifdef __APPLE__ @@ -521,7 +521,7 @@ Renderer::~Renderer() void Renderer::DrawDebugInfo() { // Reset viewport for drawing text - glViewport(0, 0, OpenGL_GetBackbufferWidth(), OpenGL_GetBackbufferHeight()); + glViewport(0, 0, GLInterface->GetBackBufferWidth(), GLInterface->GetBackBufferHeight()); // Draw various messages on the screen, like FPS, statistics, etc. char debugtext_buffer[8192]; char *p = debugtext_buffer; @@ -598,8 +598,8 @@ void Renderer::DrawDebugInfo() void Renderer::RenderText(const char *text, int left, int top, u32 color) { - const int nBackbufferWidth = (int)OpenGL_GetBackbufferWidth(); - const int nBackbufferHeight = (int)OpenGL_GetBackbufferHeight(); + const int nBackbufferWidth = (int)GLInterface->GetBackBufferWidth(); + const int nBackbufferHeight = (int)GLInterface->GetBackBufferHeight(); glColor4f(((color>>16) & 0xff)/255.0f, ((color>> 8) & 0xff)/255.0f, ((color>> 0) & 0xff)/255.0f, ((color>>24) & 0xFF)/255.0f); @@ -1294,7 +1294,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons SetWindowSize(fbWidth, fbHeight); - OpenGL_Update(); // just updates the render window position and the backbuffer size + GLInterface->Update(); // just updates the render window position and the backbuffer size bool xfbchanged = false; @@ -1308,8 +1308,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons } bool WindowResized = false; - int W = (int)OpenGL_GetBackbufferWidth(); - int H = (int)OpenGL_GetBackbufferHeight(); + int W = (int)GLInterface->GetBackBufferWidth(); + int H = (int)GLInterface->GetBackBufferHeight(); if (W != s_backbuffer_width || H != s_backbuffer_height || s_LastEFBScale != g_ActiveConfig.iEFBScale) { WindowResized = true; @@ -1354,7 +1354,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons GL_REPORT_ERRORD(); // Copy the rendered frame to the real window - OpenGL_SwapBuffers(); + GLInterface->SwapBuffers(); GL_REPORT_ERRORD(); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp index fb26ba2781..f52ec917e2 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp @@ -165,7 +165,8 @@ bool VideoBackend::Initialize(void *&window_handle) g_Config.VerifyValidity(); UpdateActiveConfig(); - if (!OpenGL_Create(window_handle)) + InitInterface(); + if (!GLInterface->CreateWindow(window_handle)) return false; s_BackendInitialized = true; @@ -177,7 +178,7 @@ bool VideoBackend::Initialize(void *&window_handle) // Run from the graphics thread void VideoBackend::Video_Prepare() { - OpenGL_MakeCurrent(); + GLInterface->MakeCurrent(); g_renderer = new Renderer; @@ -236,7 +237,7 @@ void VideoBackend::Shutdown() g_renderer = NULL; g_texture_cache = NULL; } - OpenGL_Shutdown(); + GLInterface->Shutdown(); } } diff --git a/Source/Plugins/Plugin_VideoSoftware/CMakeLists.txt b/Source/Plugins/Plugin_VideoSoftware/CMakeLists.txt index 0ba90d1537..15db15e654 100644 --- a/Source/Plugins/Plugin_VideoSoftware/CMakeLists.txt +++ b/Source/Plugins/Plugin_VideoSoftware/CMakeLists.txt @@ -26,13 +26,25 @@ if(wxWidgets_FOUND) endif(wxWidgets_FOUND) set(LIBS videocommon - GLEW SOIL common - ${OPENGL_LIBRARIES} ${X11_LIBRARIES} ${wxWidgets_LIBRARIES}) +if(USE_EGL) + set(LIBS ${LIBS} + EGL) +endif() +if(USE_GLES) + set(SRCS ${SRCS} + ../Plugin_VideoOGL/Src/GLUtil.cpp) + set(LIBS ${LIBS} + GLESv2) +else() + set(LIBS ${LIBS} + GLEW + ${OPENGL_LIBRARIES}) +endif() if(NOT (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")) set(LIBS ${LIBS} clrun) endif() diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/EfbCopy.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/EfbCopy.cpp index 50e6998a74..95566d0e26 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/EfbCopy.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/EfbCopy.cpp @@ -25,7 +25,6 @@ #include "DebugUtil.h" #include "HwRasterizer.h" #include "SWCommandProcessor.h" -#include "../../Plugin_VideoOGL/Src/GLUtil.h" #include "HW/Memmap.h" #include "Core.h" @@ -33,7 +32,7 @@ namespace EfbCopy { void CopyToXfb() { - OpenGL_Update(); // just updates the render window position and the backbuffer size + GLInterface->Update(); // just updates the render window position and the backbuffer size if (!g_SWVideoConfig.bHwRasterizer) { diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/HwRasterizer.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/HwRasterizer.cpp index 8736066524..a31fdaedd8 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/HwRasterizer.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/HwRasterizer.cpp @@ -26,6 +26,17 @@ #include "DebugUtil.h" #define TEMP_SIZE (1024*1024*4) +#ifdef USE_GLES +#define PREC "highp" +#define TEX2D GL_TEXTURE_2D +#define TEXTYPE "sampler2D" +#define TEXFUNC "texture2D" +#else +#define PREC +#define TEX2D GL_TEXTURE_RECTANGLE_ARB +#define TEXTYPE "sampler2DRect" +#define TEXFUNC "texture2DRect" +#endif namespace HwRasterizer { @@ -35,6 +46,75 @@ namespace HwRasterizer u8 *temp; + // Programs + static GLuint colProg, texProg, clearProg; + + // Color + static GLint col_apos = -1, col_atex = -1; + // Tex + static GLint tex_apos = -1, tex_atex = -1, tex_utex = -1; + // Clear shader + static GLint clear_apos = -1, clear_ucol = -1; + + void CreateShaders() + { + // Color Vertices + static const char *fragcolText = + "varying " PREC " vec4 TexCoordOut;\n" + "void main() {\n" + " gl_FragColor = TexCoordOut;\n" + "}\n"; + // Texture Vertices + static const char *fragtexText = + "varying " PREC " vec4 TexCoordOut;\n" + "uniform " TEXTYPE " Texture;\n" + "void main() {\n" + " " PREC " vec4 tmpcolor;\n" + " tmpcolor = " TEXFUNC "(Texture, TexCoordOut.xy);\n" + " gl_FragColor = tmpcolor;\n" + "}\n"; + // Clear shader + static const char *fragclearText = + "uniform vec4 Color;\n" + "void main() {\n" + " gl_FragColor = Color;\n" + "}\n"; + // Generic passthrough vertice shaders + static const char *vertShaderText = + "attribute vec4 pos;\n" + "attribute vec4 TexCoordIn;\n " + "varying vec4 TexCoordOut;\n " + "void main() {\n" + " gl_Position = pos;\n" + " TexCoordOut = TexCoordIn;\n" + "}\n"; + static const char *vertclearText = + "attribute vec4 pos;\n" + "void main() {\n" + " gl_Position = pos;\n" + "}\n"; + + // Color Program + colProg = OpenGL_CompileProgram(vertShaderText, fragcolText); + + // Texture Program + texProg = OpenGL_CompileProgram(vertShaderText, fragtexText); + + // Clear Program + clearProg = OpenGL_CompileProgram(vertclearText, fragclearText); + + // Color attributes + col_apos = glGetAttribLocation(colProg, "pos"); + col_atex = glGetAttribLocation(colProg, "TexCoordIn"); + // Texture attributes + tex_apos = glGetAttribLocation(texProg, "pos"); + tex_atex = glGetAttribLocation(texProg, "TexCoordIn"); + tex_utex = glGetUniformLocation(texProg, "Texture"); + // Clear attributes + clear_apos = glGetAttribLocation(clearProg, "pos"); + clear_ucol = glGetUniformLocation(clearProg, "Color"); + } + void Init() { efbHalfWidth = EFB_WIDTH / 2.0f; @@ -42,23 +122,72 @@ namespace HwRasterizer temp = (u8*)AllocateMemoryPages(TEMP_SIZE); } + void Shutdown() + { + glDeleteProgram(colProg); + glDeleteProgram(texProg); + glDeleteProgram(clearProg); + } + void Prepare() + { + //legacy multitexturing: select texture channel only. + glActiveTexture(GL_TEXTURE0); + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment +#ifndef USE_GLES + glShadeModel(GL_SMOOTH); + glDisable(GL_BLEND); + glClearDepth(1.0f); + glEnable(GL_SCISSOR_TEST); + glDisable(GL_LIGHTING); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glClientActiveTexture(GL_TEXTURE0); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glEnable(GL_TEXTURE_RECTANGLE_ARB); + glStencilFunc(GL_ALWAYS, 0, 0); + glDisable(GL_STENCIL_TEST); +#endif + // used by hw rasterizer if it enables blending and depth test + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDepthFunc(GL_LEQUAL); + + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + + CreateShaders(); + GL_REPORT_ERRORD(); + } + static float width, height; void LoadTexture() { FourTexUnits &texUnit = bpmem.tex[0]; u32 imageAddr = texUnit.texImage3[0].image_base; - + // Texture Rectangle uses pixel coordinates + // While GLES uses texture coordinates +#ifdef USE_GLES + width = texUnit.texImage0[0].width; + height = texUnit.texImage0[0].height; +#else + width = 1; + height = 1; +#endif TexCacheEntry &cacheEntry = textures[imageAddr]; cacheEntry.Update(); + GL_REPORT_ERRORD(); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, cacheEntry.texture); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, texUnit.texMode0[0].mag_filter ? GL_LINEAR : GL_NEAREST); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, (texUnit.texMode0[0].min_filter >= 4) ? GL_LINEAR : GL_NEAREST); + glBindTexture(TEX2D, cacheEntry.texture); + glTexParameteri(TEX2D, GL_TEXTURE_MAG_FILTER, texUnit.texMode0[0].mag_filter ? GL_LINEAR : GL_NEAREST); + glTexParameteri(TEX2D, GL_TEXTURE_MIN_FILTER, (texUnit.texMode0[0].min_filter >= 4) ? GL_LINEAR : GL_NEAREST); + GL_REPORT_ERRORD(); } void BeginTriangles() { // disabling depth test sometimes allows more things to be visible + GL_REPORT_ERRORD(); glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); @@ -66,51 +195,121 @@ namespace HwRasterizer if (hasTexture) LoadTexture(); + GL_REPORT_ERRORD(); } void EndTriangles() { - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); - + glBindTexture(TEX2D, 0); glDisable(GL_DEPTH_TEST); glDisable(GL_BLEND); } - void DrawColorVertex(OutputVertexData *v) + void DrawColorVertex(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2) { - glColor3ub(v->color[0][OutputVertexData::RED_C], v->color[0][OutputVertexData::GRN_C], v->color[0][OutputVertexData::BLU_C]); - glVertex3f(v->screenPosition.x / efbHalfWidth - 1.0f, 1.0f - v->screenPosition.y / efbHalfHeight, v->screenPosition.z / (float)0x00ffffff); + float x0 = (v0->screenPosition.x / efbHalfWidth) - 1.0f; + float y0 = 1.0f - (v0->screenPosition.y / efbHalfHeight); + float z0 = v0->screenPosition.z / (float)0x00ffffff; + + float x1 = (v1->screenPosition.x / efbHalfWidth) - 1.0f; + float y1 = 1.0f - (v1->screenPosition.y / efbHalfHeight); + float z1 = v1->screenPosition.z / (float)0x00ffffff; + + float x2 = (v2->screenPosition.x / efbHalfWidth) - 1.0f; + float y2 = 1.0f - (v2->screenPosition.y / efbHalfHeight); + float z2 = v2->screenPosition.z / (float)0x00ffffff; + + float r0 = v0->color[0][OutputVertexData::RED_C] / 255.0f; + float g0 = v0->color[0][OutputVertexData::GRN_C] / 255.0f; + float b0 = v0->color[0][OutputVertexData::BLU_C] / 255.0f; + + float r1 = v1->color[0][OutputVertexData::RED_C] / 255.0f; + float g1 = v1->color[0][OutputVertexData::GRN_C] / 255.0f; + float b1 = v1->color[0][OutputVertexData::BLU_C] / 255.0f; + + float r2 = v2->color[0][OutputVertexData::RED_C] / 255.0f; + float g2 = v2->color[0][OutputVertexData::GRN_C] / 255.0f; + float b2 = v2->color[0][OutputVertexData::BLU_C] / 255.0f; + + static const GLfloat verts[3][3] = { + { x0, y0, z0 }, + { x1, y1, z1 }, + { x2, y2, z2 } + }; + static const GLfloat col[3][4] = { + { r0, g0, b0, 0.1f }, + { r1, g1, b1, 0.1f }, + { r2, g2, b2, 0.1f } + }; + { + glUseProgram(colProg); + glEnableVertexAttribArray(col_apos); + glEnableVertexAttribArray(col_atex); + + glVertexAttribPointer(col_apos, 3, GL_FLOAT, GL_FALSE, 0, verts); + glVertexAttribPointer(col_atex, 4, GL_FLOAT, GL_FALSE, 0, col); + glDrawArrays(GL_TRIANGLES, 0, 3); + glDisableVertexAttribArray(col_atex); + glDisableVertexAttribArray(col_apos); + } + GL_REPORT_ERRORD(); } - void DrawTextureVertex(OutputVertexData *v) + void DrawTextureVertex(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2) { - float s = v->texCoords[0].x; - float t = v->texCoords[0].y; - glTexCoord2f(s, t); + float x0 = (v0->screenPosition.x / efbHalfWidth) - 1.0f; + float y0 = 1.0f - (v0->screenPosition.y / efbHalfHeight); + float z0 = v0->screenPosition.z; - float x = (v->screenPosition.x / efbHalfWidth) - 1.0f; - float y = 1.0f - (v->screenPosition.y / efbHalfHeight); - float z = v->screenPosition.z; - glVertex3f(x, y, z); + float x1 = (v1->screenPosition.x / efbHalfWidth) - 1.0f; + float y1 = 1.0f - (v1->screenPosition.y / efbHalfHeight); + float z1 = v1->screenPosition.z; + + float x2 = (v2->screenPosition.x / efbHalfWidth) - 1.0f; + float y2 = 1.0f - (v2->screenPosition.y / efbHalfHeight); + float z2 = v2->screenPosition.z; + + float s0 = v0->texCoords[0].x / width; + float t0 = v0->texCoords[0].y / height; + + float s1 = v1->texCoords[0].x / width; + float t1 = v1->texCoords[0].y / height; + + float s2 = v2->texCoords[0].x / width; + float t2 = v2->texCoords[0].y / width; + + static const GLfloat verts[3][3] = { + { x0, y0, z0 }, + { x1, y1, z1 }, + { x2, y2, z2 } + }; + static const GLfloat tex[3][2] = { + { s0, t0 }, + { s1, t1 }, + { s2, t2 } + }; + { + glUseProgram(texProg); + glEnableVertexAttribArray(tex_apos); + glEnableVertexAttribArray(tex_atex); + + glVertexAttribPointer(tex_apos, 3, GL_FLOAT, GL_FALSE, 0, verts); + glVertexAttribPointer(tex_atex, 2, GL_FLOAT, GL_FALSE, 0, tex); + glUniform1i(tex_utex, 0); + glDrawArrays(GL_TRIANGLES, 0, 3); + glDisableVertexAttribArray(tex_atex); + glDisableVertexAttribArray(tex_apos); + } + GL_REPORT_ERRORD(); } void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2) { - glBegin(GL_TRIANGLES); - if (hasTexture) - { - DrawTextureVertex(v0); - DrawTextureVertex(v1); - DrawTextureVertex(v2); - } - else - { - DrawColorVertex(v0); - DrawColorVertex(v1); - DrawColorVertex(v2); - } - glEnd(); - } + if (hasTexture) + DrawTextureVertex(v0, v1, v2); + else + DrawColorVertex(v0, v1, v2); + } void Clear() { @@ -124,17 +323,21 @@ namespace HwRasterizer GLfloat right = (GLfloat)(left + bpmem.copyTexSrcWH.x + 1) / efbHalfWidth - 1.0f; GLfloat bottom = 1.0f - (GLfloat)(top + bpmem.copyTexSrcWH.y + 1) / efbHalfHeight; GLfloat depth = (GLfloat)bpmem.clearZValue / (GLfloat)0x00ffffff; - - glBegin(GL_QUADS); - glColor4ub(r, g, b, a); - glVertex3f(left, top, depth); - glColor4ub(r, g, b, a); - glVertex3f(right, top, depth); - glColor4ub(r, g, b, a); - glVertex3f(right, bottom, depth); - glColor4ub(r, g, b, a); - glVertex3f(left, bottom, depth); - glEnd(); + static const GLfloat verts[4][3] = { + { left, top, depth }, + { right, top, depth }, + { right, bottom, depth }, + { left, bottom, depth } + }; + { + glUseProgram(clearProg); + glVertexAttribPointer(clear_apos, 3, GL_FLOAT, GL_FALSE, 0, verts); + glUniform4f(clear_ucol, r, g, b, a); + glEnableVertexAttribArray(col_apos); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glDisableVertexAttribArray(col_apos); + } + GL_REPORT_ERRORD(); } TexCacheEntry::TexCacheEntry() @@ -158,9 +361,14 @@ namespace HwRasterizer DebugUtil::GetTextureBGRA(temp, 0, 0, width, height); glGenTextures(1, (GLuint *)&texture); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, (GLsizei)width, (GLsizei)height, 0, GL_BGRA, GL_UNSIGNED_BYTE, temp); - } + glBindTexture(TEX2D, texture); +#ifdef USE_GLES + glTexImage2D(TEX2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0, GL_RGBA, GL_UNSIGNED_BYTE, temp); +#else + glTexImage2D(TEX2D, 0, GL_RGBA8, (GLsizei)width, (GLsizei)height, 0, GL_BGRA, GL_UNSIGNED_BYTE, temp); +#endif + GL_REPORT_ERRORD(); + } void TexCacheEntry::Destroy() { diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/HwRasterizer.h b/Source/Plugins/Plugin_VideoSoftware/Src/HwRasterizer.h index 568c313215..9f07a44b19 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/HwRasterizer.h +++ b/Source/Plugins/Plugin_VideoSoftware/Src/HwRasterizer.h @@ -28,6 +28,9 @@ struct OutputVertexData; namespace HwRasterizer { void Init(); + void Shutdown(); + + void Prepare(); void BeginTriangles(); void EndTriangles(); diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWRenderer.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWRenderer.cpp index 3923ed0840..982a8f11da 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWRenderer.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWRenderer.cpp @@ -16,17 +16,35 @@ // http://code.google.com/p/dolphin-emu/ #include "Common.h" +#include #include "../../Plugin_VideoOGL/Src/GLUtil.h" +#include "../../Plugin_VideoOGL/Src/RasterFont.h" #include "SWRenderer.h" #include "SWStatistics.h" -#include "../../Plugin_VideoOGL/Src/RasterFont.h" - -#define VSYNC_ENABLED 0 static GLuint s_RenderTarget = 0; +static GLint attr_pos = -1, attr_tex = -1; +static GLint uni_tex = -1; +static GLuint program; + +#ifdef USE_GLES +#define PREC "highp" +#define TEX2D GL_TEXTURE_2D +#define TEXTYPE "sampler2D" +#define TEXFUNC "texture2D" +#else +#define PREC +#define TEX2D GL_TEXTURE_RECTANGLE_ARB +#define TEXTYPE "sampler2DRect" +#define TEXFUNC "texture2DRect" +#endif + + +#ifndef USE_GLES RasterFont* s_pfont = NULL; +#endif void SWRenderer::Init() { @@ -34,79 +52,68 @@ void SWRenderer::Init() void SWRenderer::Shutdown() { + glDeleteProgram(program); glDeleteTextures(1, &s_RenderTarget); +#ifndef USE_GLES + delete s_pfont; + s_pfont = 0; +#endif +} - delete s_pfont; - s_pfont = 0; +void CreateShaders() +{ + static const char *fragShaderText = + "varying " PREC " vec2 TexCoordOut;\n" + "uniform " TEXTYPE " Texture;\n" + "void main() {\n" + " " PREC " vec4 tmpcolor;\n" + " tmpcolor = " TEXFUNC "(Texture, TexCoordOut);\n" + " gl_FragColor = tmpcolor;\n" + "}\n"; + static const char *vertShaderText = + "attribute vec4 pos;\n" + "attribute vec2 TexCoordIn;\n " + "varying vec2 TexCoordOut;\n " + "void main() {\n" + " gl_Position = pos;\n" + " TexCoordOut = TexCoordIn;\n" + "}\n"; + + program = OpenGL_CompileProgram(vertShaderText, fragShaderText); + + glUseProgram(program); + + uni_tex = glGetUniformLocation(program, "Texture"); + attr_pos = glGetAttribLocation(program, "pos"); + attr_tex = glGetAttribLocation(program, "TexCoordIn"); } void SWRenderer::Prepare() { - OpenGL_MakeCurrent(); - - // Init extension support. - if (glewInit() != GLEW_OK) { - ERROR_LOG(VIDEO, "glewInit() failed!Does your video card support OpenGL 2.x?"); - return; - } - - // Handle VSync on/off -#ifdef _WIN32 - if (WGLEW_EXT_swap_control) - wglSwapIntervalEXT(VSYNC_ENABLED); - else - ERROR_LOG(VIDEO, "no support for SwapInterval (framerate clamped to monitor refresh rate)Does your video card support OpenGL 2.x?"); -#elif defined(HAVE_X11) && HAVE_X11 - if (glXSwapIntervalSGI) - glXSwapIntervalSGI(VSYNC_ENABLED); - else - ERROR_LOG(VIDEO, "no support for SwapInterval (framerate clamped to monitor refresh rate)"); -#endif - - glStencilFunc(GL_ALWAYS, 0, 0); - // used by hw rasterizer if it enables blending and depth test - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDepthFunc(GL_LEQUAL); - - glShadeModel(GL_SMOOTH); - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClearDepth(1.0f); - glEnable(GL_SCISSOR_TEST); - + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment - - glDisable(GL_LIGHTING); - glDisable(GL_BLEND); - glDisable(GL_STENCIL_TEST); - //glDisable(GL_SCISSOR_TEST); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - s_pfont = new RasterFont(); - - // legacy multitexturing: select texture channel only. - glActiveTexture(GL_TEXTURE0); - glClientActiveTexture(GL_TEXTURE0); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glGenTextures(1, &s_RenderTarget); + + CreateShaders(); +#ifndef USE_GLES + s_pfont = new RasterFont(); glEnable(GL_TEXTURE_RECTANGLE_ARB); +#endif + GL_REPORT_ERRORD(); } void SWRenderer::RenderText(const char* pstr, int left, int top, u32 color) { - int nBackbufferWidth = (int)OpenGL_GetBackbufferWidth(); - int nBackbufferHeight = (int)OpenGL_GetBackbufferHeight(); + int nBackbufferWidth = (int)GLInterface->GetBackBufferWidth(); + int nBackbufferHeight = (int)GLInterface->GetBackBufferHeight(); +#ifndef USE_GLES glColor4f(((color>>16) & 0xff)/255.0f, ((color>> 8) & 0xff)/255.0f, ((color>> 0) & 0xff)/255.0f, ((color>>24) & 0xFF)/255.0f); - s_pfont->printMultilineText(pstr, - left * 2.0f / (float)nBackbufferWidth - 1, - 1 - top * 2.0f / (float)nBackbufferHeight, - 0, nBackbufferWidth, nBackbufferHeight); + s_pfont->printMultilineText(pstr, + left * 2.0f / (float)nBackbufferWidth - 1, + 1 - top * 2.0f / (float)nBackbufferHeight, + 0, nBackbufferWidth, nBackbufferHeight); +#endif } void SWRenderer::DrawDebugText() @@ -139,31 +146,56 @@ void SWRenderer::DrawDebugText() void SWRenderer::DrawTexture(u8 *texture, int width, int height) { - GLsizei glWidth = (GLsizei)OpenGL_GetBackbufferWidth(); - GLsizei glHeight = (GLsizei)OpenGL_GetBackbufferHeight(); + GLsizei glWidth = (GLsizei)GLInterface->GetBackBufferWidth(); + GLsizei glHeight = (GLsizei)GLInterface->GetBackBufferHeight(); // Update GLViewPort glViewport(0, 0, glWidth, glHeight); glScissor(0, 0, glWidth, glHeight); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_RenderTarget); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, (GLsizei)width, (GLsizei)height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glBindTexture(TEX2D, s_RenderTarget); - GL_REPORT_ERRORD(); + glTexImage2D(TEX2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture); + glTexParameteri(TEX2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(TEX2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); GLfloat u_max = (GLfloat)width; GLfloat v_max = (GLfloat)glHeight; - - glBegin(GL_QUADS); - glTexCoord2f(0, v_max); glVertex2f(-1, -1); - glTexCoord2f(0, 0); glVertex2f(-1, 1); - glTexCoord2f(u_max, 0); glVertex2f( 1, 1); - glTexCoord2f(u_max, v_max); glVertex2f( 1, -1); - glEnd(); + + static const GLfloat verts[4][2] = { + { -1, -1}, // Left top + { -1, 1}, // left bottom + { 1, 1}, // right bottom + { 1, -1} // right top + }; + //Texture rectangle uses pixel coordinates +#ifndef USE_GLES + static const GLfloat texverts[4][2] = { + {0, v_max}, + {0, 0}, + {u_max, 0}, + {u_max, v_max} + }; +#else + static const GLfloat texverts[4][2] = { + {0, 1}, + {0, 0}, + {1, 0}, + {1, 1} + }; +#endif + glVertexAttribPointer(attr_pos, 2, GL_FLOAT, GL_FALSE, 0, verts); + glVertexAttribPointer(attr_tex, 2, GL_FLOAT, GL_FALSE, 0, texverts); + glEnableVertexAttribArray(attr_pos); + glEnableVertexAttribArray(attr_tex); + glActiveTexture(GL_TEXTURE0); + glUniform1i(uni_tex, 0); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glDisableVertexAttribArray(attr_pos); + glDisableVertexAttribArray(attr_tex); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); + glBindTexture(TEX2D, 0); + GL_REPORT_ERRORD(); } void SWRenderer::SwapBuffer() @@ -172,15 +204,13 @@ void SWRenderer::SwapBuffer() glFlush(); - OpenGL_SwapBuffers(); + GLInterface->SwapBuffers(); - GL_REPORT_ERRORD(); - swstats.ResetFrame(); - // Clear framebuffer - glClearColor(0, 0, 0, 0); - glClearDepth(1.0); +#ifndef USE_GLES + glClearDepth(1.0f); +#endif glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); GL_REPORT_ERRORD(); diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWVideoConfig.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWVideoConfig.cpp index 05a6cdddf2..7f7ef6b0f8 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWVideoConfig.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWVideoConfig.cpp @@ -51,7 +51,7 @@ void SWVideoConfig::Load(const char* ini_file) iniFile.Get("Hardware", "Fullscreen", &bFullscreen, 0); // Hardware iniFile.Get("Hardware", "RenderToMainframe", &renderToMainframe, false); - iniFile.Get("Rendering", "HwRasterizer", &bHwRasterizer, false); + iniFile.Get("Rendering", "HwRasterizer", &bHwRasterizer, true); iniFile.Get("Info", "ShowStats", &bShowStats, false); diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp index 3c6fdcca38..1c18b1c165 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp @@ -40,6 +40,8 @@ #include "VideoBackend.h" #include "Core.h" +#define VSYNC_ENABLED 0 + namespace SW { @@ -69,8 +71,9 @@ void VideoSoftware::ShowConfig(void *_hParent) bool VideoSoftware::Initialize(void *&window_handle) { g_SWVideoConfig.Load((File::GetUserPath(D_CONFIG_IDX) + "gfx_software.ini").c_str()); + InitInterface(); - if (!OpenGL_Create(window_handle)) + if (!GLInterface->CreateWindow(window_handle)) { INFO_LOG(VIDEO, "%s", "SWRenderer::Create failed\n"); return false; @@ -83,8 +86,10 @@ bool VideoSoftware::Initialize(void *&window_handle) OpcodeDecoder::Init(); Clipper::Init(); Rasterizer::Init(); - HwRasterizer::Init(); - SWRenderer::Init(); + if (g_SWVideoConfig.bHwRasterizer) + HwRasterizer::Init(); + else + SWRenderer::Init(); DebugUtil::Init(); return true; @@ -124,14 +129,44 @@ void VideoSoftware::EmuStateChange(EMUSTATE_CHANGE newState) void VideoSoftware::Shutdown() { - SWRenderer::Shutdown(); - OpenGL_Shutdown(); + if (g_SWVideoConfig.bHwRasterizer) + HwRasterizer::Shutdown(); + else + SWRenderer::Shutdown(); + GLInterface->Shutdown(); } // This is called after Video_Initialize() from the Core void VideoSoftware::Video_Prepare() -{ - SWRenderer::Prepare(); +{ + GLInterface->MakeCurrent(); + // Init extension support. + { +#ifndef USE_GLES + if (glewInit() != GLEW_OK) { + ERROR_LOG(VIDEO, "glewInit() failed!Does your video card support OpenGL 2.x?"); + return; + } + + // Handle VSync on/off +#ifdef _WIN32 + if (WGLEW_EXT_swap_control) + wglSwapIntervalEXT(VSYNC_ENABLED); + else + ERROR_LOG(VIDEO, "no support for SwapInterval (framerate clamped to monitor refresh rate)Does your video card support OpenGL 2.x?"); +#elif defined(HAVE_X11) && HAVE_X11 + if (glXSwapIntervalSGI) + glXSwapIntervalSGI(VSYNC_ENABLED); + else + ERROR_LOG(VIDEO, "no support for SwapInterval (framerate clamped to monitor refresh rate)"); +#endif +#endif + } + + if (g_SWVideoConfig.bHwRasterizer) + HwRasterizer::Prepare(); + else + SWRenderer::Prepare(); INFO_LOG(VIDEO, "Video backend initialized."); } @@ -273,20 +308,7 @@ writeFn32 VideoSoftware::Video_PEWrite32() // Draw messages on top of the screen unsigned int VideoSoftware::PeekMessages() { -#ifdef _WIN32 - // TODO: peekmessage - MSG msg; - while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) - { - if (msg.message == WM_QUIT) - return FALSE; - TranslateMessage(&msg); - DispatchMessage(&msg); - } - return TRUE; -#else - return false; -#endif + return GLInterface->PeekMessages(); } // Show the current FPS @@ -294,7 +316,7 @@ void VideoSoftware::UpdateFPSDisplay(const char *text) { char temp[100]; snprintf(temp, sizeof temp, "%s | Software | %s", scm_rev_str, text); - OpenGL_SetWindowText(temp); + GLInterface->UpdateFPSDisplay(temp); } }