Advertisement
Guest User

vidext.c

a guest
Dec 3rd, 2014
221
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 15.29 KB | None | 0 0
  1. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  2.  *   Mupen64plus-core - api/vidext.c                                       *
  3.  *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
  4.  *   Copyright (C) 2009 Richard Goedeken                                   *
  5.  *                                                                         *
  6.  *   This program is free software; you can redistribute it and/or modify  *
  7.  *   it under the terms of the GNU General Public License as published by  *
  8.  *   the Free Software Foundation; either version 2 of the License, or     *
  9.  *   (at your option) any later version.                                   *
  10.  *                                                                         *
  11.  *   This program is distributed in the hope that it will be useful,       *
  12.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
  13.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
  14.  *   GNU General Public License for more details.                          *
  15.  *                                                                         *
  16.  *   You should have received a copy of the GNU General Public License     *
  17.  *   along with this program; if not, write to the                         *
  18.  *   Free Software Foundation, Inc.,                                       *
  19.  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
  20.  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  21.                        
  22. /* This file contains the Core video extension functions which will be exported
  23.  * outside of the core library.
  24.  */
  25.  
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <SDL.h>
  29.  
  30. #define M64P_CORE_PROTOTYPES 1
  31. #include "m64p_types.h"
  32. #include "m64p_vidext.h"
  33. #include "vidext.h"
  34. #include "callbacks.h"
  35. #ifdef HAVE_EGL
  36. #include "egl_windows.h"
  37. #endif
  38. #include "../osd/osd.h"
  39.  
  40. #if SDL_VERSION_ATLEAST(2,0,0)
  41. #include "vidext_sdl2_compat.h"
  42. #endif
  43.  
  44. /* local variables */
  45. static m64p_video_extension_functions l_ExternalVideoFuncTable = {10, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
  46. static int l_VideoExtensionActive = 0;
  47. static int l_VideoOutputActive = 0;
  48. static int l_Fullscreen = 0;
  49. static SDL_Surface *l_pScreen = NULL;
  50.  
  51. /* global function for use by frontend.c */
  52. m64p_error OverrideVideoFunctions(m64p_video_extension_functions *VideoFunctionStruct)
  53. {
  54.     /* check input data */
  55.     if (VideoFunctionStruct == NULL)
  56.         return M64ERR_INPUT_ASSERT;
  57.     if (VideoFunctionStruct->Functions < 11)
  58.         return M64ERR_INPUT_INVALID;
  59.  
  60.     /* disable video extension if any of the function pointers are NULL */
  61.     if (VideoFunctionStruct->VidExtFuncInit == NULL ||
  62.         VideoFunctionStruct->VidExtFuncQuit == NULL ||
  63.         VideoFunctionStruct->VidExtFuncListModes == NULL ||
  64.         VideoFunctionStruct->VidExtFuncSetMode == NULL ||
  65.         VideoFunctionStruct->VidExtFuncGLGetProc == NULL ||
  66.         VideoFunctionStruct->VidExtFuncGLSetAttr == NULL ||
  67.         VideoFunctionStruct->VidExtFuncGLGetAttr == NULL ||
  68.         VideoFunctionStruct->VidExtFuncGLSwapBuf == NULL ||
  69.         VideoFunctionStruct->VidExtFuncSetCaption == NULL ||
  70.         VideoFunctionStruct->VidExtFuncToggleFS == NULL ||
  71.         VideoFunctionStruct->VidExtFuncResizeWindow == NULL)
  72.     {
  73.         l_ExternalVideoFuncTable.Functions = 11;
  74.         memset(&l_ExternalVideoFuncTable.VidExtFuncInit, 0, 11 * sizeof(void *));
  75.         l_VideoExtensionActive = 0;
  76.         return M64ERR_SUCCESS;
  77.     }
  78.  
  79.     /* otherwise copy in the override function pointers */
  80.     memcpy(&l_ExternalVideoFuncTable, VideoFunctionStruct, sizeof(m64p_video_extension_functions));
  81.     l_VideoExtensionActive = 1;
  82.     return M64ERR_SUCCESS;
  83. }
  84.  
  85. int VidExt_InFullscreenMode(void)
  86. {
  87.     return l_Fullscreen;
  88. }
  89.  
  90. int VidExt_VideoRunning(void)
  91. {
  92.     return l_VideoOutputActive;
  93. }
  94.  
  95. /* video extension functions to be called by the video plugin */
  96. EXPORT m64p_error CALL VidExt_Init(void)
  97. {
  98.     /* call video extension override if necessary */
  99.     if (l_VideoExtensionActive)
  100.         return (*l_ExternalVideoFuncTable.VidExtFuncInit)();
  101.  
  102.     if (SDL_InitSubSystem(SDL_INIT_VIDEO) == -1)
  103.     {
  104.         DebugMessage(M64MSG_ERROR, "SDL video subsystem init failed: %s", SDL_GetError());
  105.         return M64ERR_SYSTEM_FAIL;
  106.     }
  107.  
  108.     return M64ERR_SUCCESS;
  109. }
  110.  
  111. EXPORT m64p_error CALL VidExt_Quit(void)
  112. {
  113.     /* call video extension override if necessary */
  114.     if (l_VideoExtensionActive)
  115.     {
  116.         m64p_error rval = (*l_ExternalVideoFuncTable.VidExtFuncQuit)();
  117.         if (rval == M64ERR_SUCCESS)
  118.         {
  119.             l_VideoOutputActive = 0;
  120.             StateChanged(M64CORE_VIDEO_MODE, M64VIDEO_NONE);
  121.         }
  122.         return rval;
  123.     }
  124.  
  125.     if (!SDL_WasInit(SDL_INIT_VIDEO))
  126.         return M64ERR_NOT_INIT;
  127.  
  128. #ifdef HAVE_EGL
  129.     destroy_egl_windows();
  130. #endif
  131.  
  132.     SDL_ShowCursor(SDL_ENABLE);
  133.     SDL_QuitSubSystem(SDL_INIT_VIDEO);
  134.     l_pScreen = NULL;
  135.     l_VideoOutputActive = 0;
  136.     StateChanged(M64CORE_VIDEO_MODE, M64VIDEO_NONE);
  137.  
  138.     return M64ERR_SUCCESS;
  139. }
  140.  
  141. EXPORT m64p_error CALL VidExt_ListFullscreenModes(m64p_2d_size *SizeArray, int *NumSizes)
  142. {
  143.     const SDL_VideoInfo *videoInfo;
  144.     unsigned int videoFlags;
  145.     SDL_Rect **modes;
  146.     int i;
  147.  
  148.     /* call video extension override if necessary */
  149.     if (l_VideoExtensionActive)
  150.         return (*l_ExternalVideoFuncTable.VidExtFuncListModes)(SizeArray, NumSizes);
  151.  
  152.     if (!SDL_WasInit(SDL_INIT_VIDEO))
  153.         return M64ERR_NOT_INIT;
  154.  
  155.     /* get a list of SDL video modes */
  156.     videoFlags = SDL_OPENGL | SDL_FULLSCREEN;
  157.  
  158.     if ((videoInfo = SDL_GetVideoInfo()) == NULL)
  159.     {
  160.         DebugMessage(M64MSG_ERROR, "SDL_GetVideoInfo query failed: %s", SDL_GetError());
  161.         return M64ERR_SYSTEM_FAIL;
  162.     }
  163.  
  164.     if(videoInfo->hw_available)
  165.         videoFlags |= SDL_HWSURFACE;
  166.     else
  167.         videoFlags |= SDL_SWSURFACE;
  168.  
  169.     modes = SDL_ListModes(NULL, videoFlags);
  170.  
  171.     if (modes == (SDL_Rect **) 0 || modes == (SDL_Rect **) -1)
  172.     {
  173.         DebugMessage(M64MSG_WARNING, "No fullscreen SDL video modes available");
  174.         *NumSizes = 0;
  175.         return M64ERR_SUCCESS;
  176.     }
  177.  
  178.     i = 0;
  179.     while (i < *NumSizes && modes[i] != NULL)
  180.     {
  181.         SizeArray[i].uiWidth  = modes[i]->w;
  182.         SizeArray[i].uiHeight = modes[i]->h;
  183.         i++;
  184.     }
  185.  
  186.     *NumSizes = i;
  187.  
  188.     return M64ERR_SUCCESS;
  189. }
  190.  
  191. EXPORT m64p_error CALL VidExt_SetVideoMode(int Width, int Height, int BitsPerPixel, m64p_video_mode ScreenMode, m64p_video_flags Flags)
  192. {
  193.     const SDL_VideoInfo *videoInfo;
  194.     int videoFlags = 0;
  195.  
  196.     /* call video extension override if necessary */
  197.     if (l_VideoExtensionActive)
  198.     {
  199.         m64p_error rval = (*l_ExternalVideoFuncTable.VidExtFuncSetMode)(Width, Height, BitsPerPixel, ScreenMode, Flags);
  200.         l_Fullscreen = (rval == M64ERR_SUCCESS && ScreenMode == M64VIDEO_FULLSCREEN);
  201.         l_VideoOutputActive = (rval == M64ERR_SUCCESS);
  202.         if (l_VideoOutputActive)
  203.         {
  204.             StateChanged(M64CORE_VIDEO_MODE, ScreenMode);
  205.             StateChanged(M64CORE_VIDEO_SIZE, (Width << 16) | Height);
  206.         }
  207.         return rval;
  208.     }
  209.  
  210.     if (!SDL_WasInit(SDL_INIT_VIDEO))
  211.         return M64ERR_NOT_INIT;
  212.  
  213.     /* Get SDL video flags to use */
  214.     if (ScreenMode == M64VIDEO_WINDOWED)
  215.     {
  216.         videoFlags = SDL_OPENGL;
  217.         if (Flags & M64VIDEOFLAG_SUPPORT_RESIZING)
  218.             videoFlags |= SDL_RESIZABLE;
  219.     }
  220.     else if (ScreenMode == M64VIDEO_FULLSCREEN)
  221.     {
  222.         videoFlags = SDL_OPENGL | SDL_FULLSCREEN;
  223.     }
  224.     else
  225.     {
  226.         return M64ERR_INPUT_INVALID;
  227.     }
  228.  
  229.     if ((videoInfo = SDL_GetVideoInfo()) == NULL)
  230.     {
  231.         DebugMessage(M64MSG_ERROR, "SDL_GetVideoInfo query failed: %s", SDL_GetError());
  232.         return M64ERR_SYSTEM_FAIL;
  233.     }
  234.     if (videoInfo->hw_available)
  235.         videoFlags |= SDL_HWSURFACE;
  236.     else
  237.         videoFlags |= SDL_SWSURFACE;
  238.  
  239.     /* set the mode */
  240.     if (BitsPerPixel > 0)
  241.         DebugMessage(M64MSG_INFO, "Setting %i-bit video mode: %ix%i", BitsPerPixel, Width, Height);
  242.     else
  243.         DebugMessage(M64MSG_INFO, "Setting video mode: %ix%i", Width, Height);
  244.  
  245. #ifdef HAVE_EGL
  246.     l_pScreen = SDL_SetVideoMode(Width, Height, 16, SDL_HWSURFACE);
  247.     create_egl_windows();
  248. #else
  249.     l_pScreen = SDL_SetVideoMode(Width, Height, BitsPerPixel, videoFlags);
  250. #endif
  251.     if (l_pScreen == NULL)
  252.     {
  253.         DebugMessage(M64MSG_ERROR, "SDL_SetVideoMode failed: %s", SDL_GetError());
  254.         return M64ERR_SYSTEM_FAIL;
  255.     }
  256.  
  257.     SDL_ShowCursor(SDL_DISABLE);
  258.  
  259.     l_Fullscreen = (ScreenMode == M64VIDEO_FULLSCREEN);
  260.     l_VideoOutputActive = 1;
  261.     StateChanged(M64CORE_VIDEO_MODE, ScreenMode);
  262.     StateChanged(M64CORE_VIDEO_SIZE, (Width << 16) | Height);
  263.     return M64ERR_SUCCESS;
  264. }
  265.  
  266. EXPORT m64p_error CALL VidExt_ResizeWindow(int Width, int Height)
  267. {
  268.     const SDL_VideoInfo *videoInfo;
  269.     int videoFlags = 0;
  270.  
  271.     /* call video extension override if necessary */
  272.     if (l_VideoExtensionActive)
  273.     {
  274.         m64p_error rval;
  275.         // shut down the OSD
  276.         //osd_exit();
  277.         // re-create the OGL context
  278.         rval = (*l_ExternalVideoFuncTable.VidExtFuncResizeWindow)(Width, Height);
  279.         if (rval == M64ERR_SUCCESS)
  280.         {
  281.             StateChanged(M64CORE_VIDEO_SIZE, (Width << 16) | Height);
  282.             // re-create the On-Screen Display
  283.             //osd_init(Width, Height);
  284.         }
  285.         return rval;
  286.     }
  287.  
  288.     if (!l_VideoOutputActive || !SDL_WasInit(SDL_INIT_VIDEO))
  289.         return M64ERR_NOT_INIT;
  290.  
  291.     if (l_Fullscreen)
  292.     {
  293.         DebugMessage(M64MSG_ERROR, "VidExt_ResizeWindow() called in fullscreen mode.");
  294.         return M64ERR_INVALID_STATE;
  295.     }
  296.  
  297.     /* Get SDL video flags to use */
  298.     videoFlags = SDL_OPENGL | SDL_RESIZABLE;
  299.     if ((videoInfo = SDL_GetVideoInfo()) == NULL)
  300.     {
  301.         DebugMessage(M64MSG_ERROR, "SDL_GetVideoInfo query failed: %s", SDL_GetError());
  302.         return M64ERR_SYSTEM_FAIL;
  303.     }
  304.     if (videoInfo->hw_available)
  305.         videoFlags |= SDL_HWSURFACE;
  306.     else
  307.         videoFlags |= SDL_SWSURFACE;
  308.  
  309.     // destroy the On-Screen Display
  310.     //osd_exit();
  311.  
  312.     /* set the re-sizing the screen will create a new OpenGL context */
  313.     l_pScreen = SDL_SetVideoMode(Width, Height, 0, videoFlags);
  314.     if (l_pScreen == NULL)
  315.     {
  316.         DebugMessage(M64MSG_ERROR, "SDL_SetVideoMode failed: %s", SDL_GetError());
  317.         return M64ERR_SYSTEM_FAIL;
  318.     }
  319.  
  320.     StateChanged(M64CORE_VIDEO_SIZE, (Width << 16) | Height);
  321.     // re-create the On-Screen Display
  322.     //osd_init(Width, Height);
  323.     return M64ERR_SUCCESS;
  324. }
  325.  
  326. EXPORT m64p_error CALL VidExt_SetCaption(const char *Title)
  327. {
  328.     /* call video extension override if necessary */
  329.     if (l_VideoExtensionActive)
  330.         return (*l_ExternalVideoFuncTable.VidExtFuncSetCaption)(Title);
  331.  
  332.     if (!SDL_WasInit(SDL_INIT_VIDEO))
  333.         return M64ERR_NOT_INIT;
  334.  
  335.     SDL_WM_SetCaption(Title, "M64+ Video");
  336.  
  337.     return M64ERR_SUCCESS;
  338. }
  339.  
  340. EXPORT m64p_error CALL VidExt_ToggleFullScreen(void)
  341. {
  342.     /* call video extension override if necessary */
  343.     if (l_VideoExtensionActive)
  344.     {
  345.         m64p_error rval = (*l_ExternalVideoFuncTable.VidExtFuncToggleFS)();
  346.         if (rval == M64ERR_SUCCESS)
  347.         {
  348.             l_Fullscreen = !l_Fullscreen;
  349.             StateChanged(M64CORE_VIDEO_MODE, l_Fullscreen ? M64VIDEO_FULLSCREEN : M64VIDEO_WINDOWED);
  350.         }
  351.         return rval;
  352.     }
  353.  
  354.     if (!SDL_WasInit(SDL_INIT_VIDEO))
  355.         return M64ERR_NOT_INIT;
  356.  
  357.     /* TODO:
  358.      * SDL_WM_ToggleFullScreen doesn't work under Windows and others
  359.      * (see http://wiki.libsdl.org/moin.cgi/FAQWindows for explanation).
  360.      * Instead, we should call SDL_SetVideoMode with the SDL_FULLSCREEN flag.
  361.      * (see http://sdl.beuc.net/sdl.wiki/SDL_SetVideoMode), but on Windows
  362.      * this resets the OpenGL context and video plugins don't support it yet.
  363.      * Uncomment the next line to test it: */
  364.     //return VidExt_SetVideoMode(l_pScreen->w, l_pScreen->h, l_pScreen->format->BitsPerPixel, l_Fullscreen ? M64VIDEO_WINDOWED : M64VIDEO_FULLSCREEN);
  365.     if (SDL_WM_ToggleFullScreen(l_pScreen) == 1)
  366.     {
  367.         l_Fullscreen = !l_Fullscreen;
  368.         StateChanged(M64CORE_VIDEO_MODE, l_Fullscreen ? M64VIDEO_FULLSCREEN : M64VIDEO_WINDOWED);
  369.         return M64ERR_SUCCESS;
  370.     }
  371.  
  372.     return M64ERR_SYSTEM_FAIL;
  373. }
  374.  
  375. EXPORT void * CALL VidExt_GL_GetProcAddress(const char* Proc)
  376. {
  377.     /* call video extension override if necessary */
  378.     if (l_VideoExtensionActive)
  379.         return (*l_ExternalVideoFuncTable.VidExtFuncGLGetProc)(Proc);
  380.  
  381.     if (!SDL_WasInit(SDL_INIT_VIDEO))
  382.         return NULL;
  383.  
  384.     return SDL_GL_GetProcAddress(Proc);
  385. }
  386.  
  387. typedef struct {
  388.     m64p_GLattr m64Attr;
  389.     SDL_GLattr sdlAttr;
  390. } GLAttrMapNode;
  391.  
  392. static const GLAttrMapNode GLAttrMap[] = {
  393.         { M64P_GL_DOUBLEBUFFER, SDL_GL_DOUBLEBUFFER },
  394.         { M64P_GL_BUFFER_SIZE,  SDL_GL_BUFFER_SIZE },
  395.         { M64P_GL_DEPTH_SIZE,   SDL_GL_DEPTH_SIZE },
  396.         { M64P_GL_RED_SIZE,     SDL_GL_RED_SIZE },
  397.         { M64P_GL_GREEN_SIZE,   SDL_GL_GREEN_SIZE },
  398.         { M64P_GL_BLUE_SIZE,    SDL_GL_BLUE_SIZE },
  399.         { M64P_GL_ALPHA_SIZE,   SDL_GL_ALPHA_SIZE },
  400. #if SDL_VERSION_ATLEAST(1,3,0)
  401.         { M64P_GL_SWAP_CONTROL, SDL_RENDERER_PRESENTVSYNC },
  402. #else
  403.         { M64P_GL_SWAP_CONTROL, SDL_GL_SWAP_CONTROL },
  404. #endif
  405.         { M64P_GL_MULTISAMPLEBUFFERS, SDL_GL_MULTISAMPLEBUFFERS },
  406.         { M64P_GL_MULTISAMPLESAMPLES, SDL_GL_MULTISAMPLESAMPLES }};
  407. static const int mapSize = sizeof(GLAttrMap) / sizeof(GLAttrMapNode);
  408.  
  409. EXPORT m64p_error CALL VidExt_GL_SetAttribute(m64p_GLattr Attr, int Value)
  410. {
  411.     int i;
  412.  
  413.     /* call video extension override if necessary */
  414.     if (l_VideoExtensionActive)
  415.         return (*l_ExternalVideoFuncTable.VidExtFuncGLSetAttr)(Attr, Value);
  416.  
  417.     if (!SDL_WasInit(SDL_INIT_VIDEO))
  418.         return M64ERR_NOT_INIT;
  419.  
  420.     for (i = 0; i < mapSize; i++)
  421.     {
  422.         if (GLAttrMap[i].m64Attr == Attr)
  423.         {
  424.             if (SDL_GL_SetAttribute(GLAttrMap[i].sdlAttr, Value) != 0)
  425.                 return M64ERR_SYSTEM_FAIL;
  426.             return M64ERR_SUCCESS;
  427.         }
  428.     }
  429.  
  430.     return M64ERR_INPUT_INVALID;
  431. }
  432.  
  433. EXPORT m64p_error CALL VidExt_GL_GetAttribute(m64p_GLattr Attr, int *pValue)
  434. {
  435.     int i;
  436.  
  437.     /* call video extension override if necessary */
  438.     if (l_VideoExtensionActive)
  439.         return (*l_ExternalVideoFuncTable.VidExtFuncGLGetAttr)(Attr, pValue);
  440.  
  441.     if (!SDL_WasInit(SDL_INIT_VIDEO))
  442.         return M64ERR_NOT_INIT;
  443.  
  444.     for (i = 0; i < mapSize; i++)
  445.     {
  446.         if (GLAttrMap[i].m64Attr == Attr)
  447.         {
  448.             int NewValue = 0;
  449.             if (SDL_GL_GetAttribute(GLAttrMap[i].sdlAttr, &NewValue) != 0)
  450.                 return M64ERR_SYSTEM_FAIL;
  451.             *pValue = NewValue;
  452.             return M64ERR_SUCCESS;
  453.         }
  454.     }
  455.  
  456.     return M64ERR_INPUT_INVALID;
  457. }
  458.  
  459. EXPORT m64p_error CALL VidExt_GL_SwapBuffers(void)
  460. {
  461.     /* call video extension override if necessary */
  462.     if (l_VideoExtensionActive)
  463.         return (*l_ExternalVideoFuncTable.VidExtFuncGLSwapBuf)();
  464.  
  465.     if (!SDL_WasInit(SDL_INIT_VIDEO))
  466.         return M64ERR_NOT_INIT;
  467.  
  468. #ifdef HAVE_EGL
  469.     egl_swap_buffers();
  470. #else
  471.     SDL_GL_SwapBuffers();
  472. #endif
  473.     return M64ERR_SUCCESS;
  474. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement