Ejemplo n.º 1
0
 public Texture()
 {
     OpenGL.glGenTextures(1, out texture);
     OpenGL.CheckGLError();
 }
Ejemplo n.º 2
0
 public Texture(Bitmap bitmap)
 {
     OpenGL.glGenTextures(1, out texture);
     OpenGL.CheckGLError();
     SetData(bitmap);
 }
Ejemplo n.º 3
0
        public Shader(string name)
        {
            var vertexShader   = CompileShaderObject(OpenGL.GL_VERTEX_SHADER, name);
            var fragmentShader = CompileShaderObject(OpenGL.GL_FRAGMENT_SHADER, name);

            // Assemble program
            program = OpenGL.glCreateProgram();
            OpenGL.CheckGLError();

            OpenGL.glBindAttribLocation(program, VertexPosAttributeIndex, "aVertexPosition");
            OpenGL.CheckGLError();
            OpenGL.glBindAttribLocation(program, TexCoordAttributeIndex, "aVertexTexCoord");
            OpenGL.CheckGLError();
            OpenGL.glBindAttribLocation(program, TexMetadataAttributeIndex, "aVertexTexMetadata");
            OpenGL.CheckGLError();
            OpenGL.glBindFragDataLocation(program, 0, "fragColor");
            OpenGL.CheckGLError();

            OpenGL.glAttachShader(program, vertexShader);
            OpenGL.CheckGLError();
            OpenGL.glAttachShader(program, fragmentShader);
            OpenGL.CheckGLError();

            OpenGL.glLinkProgram(program);
            OpenGL.CheckGLError();
            int success;

            OpenGL.glGetProgramiv(program, OpenGL.GL_LINK_STATUS, out success);
            OpenGL.CheckGLError();
            if (success == OpenGL.GL_FALSE)
            {
                int len;
                OpenGL.glGetProgramiv(program, OpenGL.GL_INFO_LOG_LENGTH, out len);

                var log = new StringBuilder(len);
                int length;
                OpenGL.glGetProgramInfoLog(program, len, out length, log);
                Log.Write("graphics", "GL Info Log:\n{0}", log.ToString());
                throw new InvalidProgramException("Link error in shader program '{0}'".F(name));
            }

            OpenGL.glUseProgram(program);
            OpenGL.CheckGLError();

            int numUniforms;

            OpenGL.glGetProgramiv(program, OpenGL.GL_ACTIVE_UNIFORMS, out numUniforms);

            OpenGL.CheckGLError();

            var nextTexUnit = 0;

            for (var i = 0; i < numUniforms; i++)
            {
                int length, size;
                int type;
                var sb = new StringBuilder(128);
                OpenGL.glGetActiveUniform(program, i, 128, out length, out size, out type, sb);
                var sampler = sb.ToString();
                OpenGL.CheckGLError();

                if (type == OpenGL.GL_SAMPLER_2D)
                {
                    samplers.Add(sampler, nextTexUnit);

                    var loc = OpenGL.glGetUniformLocation(program, sampler);
                    OpenGL.CheckGLError();
                    OpenGL.glUniform1i(loc, nextTexUnit);
                    OpenGL.CheckGLError();

                    nextTexUnit++;
                }
            }
        }
Ejemplo n.º 4
0
        public byte[] GetData()
        {
            VerifyThreadAffinity();
            var data = new byte[4 * Size.Width * Size.Height];

            // GLES doesn't support glGetTexImage so data must be read back via a frame buffer
            if (OpenGL.Profile == GLProfile.Embedded)
            {
                // Query the active framebuffer so we can restore it afterwards
                OpenGL.glGetIntegerv(OpenGL.GL_FRAMEBUFFER_BINDING, out var lastFramebuffer);

                OpenGL.glGenFramebuffers(1, out var framebuffer);
                OpenGL.glBindFramebuffer(OpenGL.GL_FRAMEBUFFER, framebuffer);
                OpenGL.CheckGLError();

                OpenGL.glFramebufferTexture2D(OpenGL.GL_FRAMEBUFFER, OpenGL.GL_COLOR_ATTACHMENT0, OpenGL.GL_TEXTURE_2D, texture, 0);
                OpenGL.CheckGLError();

                var canReadBGRA = OpenGL.Features.HasFlag(OpenGL.GLFeatures.ESReadFormatBGRA);

                unsafe
                {
                    fixed(byte *ptr = &data[0])
                    {
                        var intPtr = new IntPtr(ptr);

                        var format = canReadBGRA ? OpenGL.GL_BGRA : OpenGL.GL_RGBA;

                        OpenGL.glReadPixels(0, 0, Size.Width, Size.Height, format, OpenGL.GL_UNSIGNED_BYTE, intPtr);
                        OpenGL.CheckGLError();
                    }
                }

                // Convert RGBA to BGRA
                if (!canReadBGRA)
                {
                    for (var i = 0; i < 4 * Size.Width * Size.Height; i += 4)
                    {
                        var temp = data[i];
                        data[i]     = data[i + 2];
                        data[i + 2] = temp;
                    }
                }

                OpenGL.glBindFramebuffer(OpenGL.GL_FRAMEBUFFER, (uint)lastFramebuffer);
                OpenGL.glDeleteFramebuffers(1, ref framebuffer);
                OpenGL.CheckGLError();
            }
            else
            {
                OpenGL.glBindTexture(OpenGL.GL_TEXTURE_2D, texture);
                unsafe
                {
                    fixed(byte *ptr = &data[0])
                    {
                        var intPtr = new IntPtr((void *)ptr);

                        OpenGL.glGetTexImage(OpenGL.GL_TEXTURE_2D, 0, OpenGL.GL_BGRA,
                                             OpenGL.GL_UNSIGNED_BYTE, intPtr);
                    }
                }

                OpenGL.CheckGLError();
            }

            return(data);
        }
Ejemplo n.º 5
0
 public void ClearDepthBuffer()
 {
     VerifyThreadAffinity();
     OpenGL.glClear(OpenGL.GL_DEPTH_BUFFER_BIT);
     OpenGL.CheckGLError();
 }
Ejemplo n.º 6
0
        public void SetBlendMode(BlendMode mode)
        {
            VerifyThreadAffinity();
            OpenGL.glBlendEquation(OpenGL.GL_FUNC_ADD);
            OpenGL.CheckGLError();

            switch (mode)
            {
            case BlendMode.None:
                OpenGL.glDisable(OpenGL.GL_BLEND);
                break;

            case BlendMode.Alpha:
                OpenGL.glEnable(OpenGL.GL_BLEND);
                OpenGL.CheckGLError();
                OpenGL.glBlendFunc(OpenGL.GL_ONE, OpenGL.GL_ONE_MINUS_SRC_ALPHA);
                break;

            case BlendMode.Additive:
            case BlendMode.Subtractive:
                OpenGL.glEnable(OpenGL.GL_BLEND);
                OpenGL.CheckGLError();
                OpenGL.glBlendFunc(OpenGL.GL_ONE, OpenGL.GL_ONE);
                if (mode == BlendMode.Subtractive)
                {
                    OpenGL.CheckGLError();
                    OpenGL.glBlendEquationSeparate(OpenGL.GL_FUNC_REVERSE_SUBTRACT, OpenGL.GL_FUNC_ADD);
                }

                break;

            case BlendMode.Multiply:
                OpenGL.glEnable(OpenGL.GL_BLEND);
                OpenGL.CheckGLError();
                OpenGL.glBlendFunc(OpenGL.GL_DST_COLOR, OpenGL.GL_ONE_MINUS_SRC_ALPHA);
                OpenGL.CheckGLError();
                break;

            case BlendMode.Multiplicative:
                OpenGL.glEnable(OpenGL.GL_BLEND);
                OpenGL.CheckGLError();
                OpenGL.glBlendFunc(OpenGL.GL_ZERO, OpenGL.GL_SRC_COLOR);
                break;

            case BlendMode.DoubleMultiplicative:
                OpenGL.glEnable(OpenGL.GL_BLEND);
                OpenGL.CheckGLError();
                OpenGL.glBlendFunc(OpenGL.GL_DST_COLOR, OpenGL.GL_SRC_COLOR);
                break;

            case BlendMode.LowAdditive:
                OpenGL.glEnable(OpenGL.GL_BLEND);
                OpenGL.CheckGLError();
                OpenGL.glBlendFunc(OpenGL.GL_DST_COLOR, OpenGL.GL_ONE);
                break;

            case BlendMode.Screen:
                OpenGL.glEnable(OpenGL.GL_BLEND);
                OpenGL.CheckGLError();
                OpenGL.glBlendFunc(OpenGL.GL_SRC_COLOR, OpenGL.GL_ONE_MINUS_SRC_COLOR);
                break;

            case BlendMode.Translucent:
                OpenGL.glEnable(OpenGL.GL_BLEND);
                OpenGL.CheckGLError();
                OpenGL.glBlendFunc(OpenGL.GL_DST_COLOR, OpenGL.GL_ONE_MINUS_DST_COLOR);
                break;
            }

            OpenGL.CheckGLError();
        }
Ejemplo n.º 7
0
 public void DisableDepthBuffer()
 {
     VerifyThreadAffinity();
     OpenGL.glDisable(OpenGL.GL_DEPTH_TEST);
     OpenGL.CheckGLError();
 }
Ejemplo n.º 8
0
 public void DrawPrimitives(PrimitiveType pt, int firstVertex, int numVertices)
 {
     VerifyThreadAffinity();
     OpenGL.glDrawArrays(ModeFromPrimitiveType(pt), firstVertex, numVertices);
     OpenGL.CheckGLError();
 }
Ejemplo n.º 9
0
 public void DisableScissor()
 {
     VerifyThreadAffinity();
     OpenGL.glDisable(OpenGL.GL_SCISSOR_TEST);
     OpenGL.CheckGLError();
 }
Ejemplo n.º 10
0
        public void PumpInput(IInputHandler inputHandler)
        {
            var mods        = MakeModifiers((int)SDL.SDL_GetModState());
            var scrollDelta = 0;

            inputHandler.ModifierKeys(mods);
            MouseInput?pendingMotion = null;

            SDL.SDL_Event e;
            while (SDL.SDL_PollEvent(out e) != 0)
            {
                switch (e.type)
                {
                case SDL.SDL_EventType.SDL_QUIT:
                    Game.Exit();
                    break;

                case SDL.SDL_EventType.SDL_WINDOWEVENT:
                {
                    switch (e.window.windowEvent)
                    {
                    case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_FOCUS_LOST:
                        Game.HasInputFocus = false;
                        break;

                    case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_FOCUS_GAINED:
                        Game.HasInputFocus = true;
                        break;
                    }

                    break;
                }

                case SDL.SDL_EventType.SDL_MOUSEBUTTONDOWN:
                {
                    if (pendingMotion != null)
                    {
                        inputHandler.OnMouseInput(pendingMotion.Value);
                        pendingMotion = null;
                    }

                    var button = MakeButton(e.button.button);
                    lastButtonBits |= button;

                    var pos = new int2(e.button.x, e.button.y);

                    inputHandler.OnMouseInput(new MouseInput(
                                                  MouseInputEvent.Down, button, scrollDelta, pos, mods,
                                                  MultiTapDetection.DetectFromMouse(e.button.button, pos)));

                    break;
                }

                case SDL.SDL_EventType.SDL_MOUSEBUTTONUP:
                {
                    if (pendingMotion != null)
                    {
                        inputHandler.OnMouseInput(pendingMotion.Value);
                        pendingMotion = null;
                    }

                    var button = MakeButton(e.button.button);
                    lastButtonBits &= ~button;

                    var pos = new int2(e.button.x, e.button.y);
                    inputHandler.OnMouseInput(new MouseInput(
                                                  MouseInputEvent.Up, button, scrollDelta, pos, mods,
                                                  MultiTapDetection.InfoFromMouse(e.button.button)));

                    break;
                }

                case SDL.SDL_EventType.SDL_MOUSEMOTION:
                {
                    pendingMotion = new MouseInput(
                        MouseInputEvent.Move, lastButtonBits, scrollDelta,
                        new int2(e.motion.x, e.motion.y), mods, 0);

                    break;
                }

                case SDL.SDL_EventType.SDL_MOUSEWHEEL:
                {
                    int x, y;
                    SDL.SDL_GetMouseState(out x, out y);
                    scrollDelta = e.wheel.y;
                    inputHandler.OnMouseInput(new MouseInput(MouseInputEvent.Scroll, MouseButton.None, scrollDelta, new int2(x, y), Modifiers.None, 0));

                    break;
                }

                case SDL.SDL_EventType.SDL_TEXTINPUT:
                {
                    var rawBytes = new byte[SDL.SDL_TEXTINPUTEVENT_TEXT_SIZE];
                    unsafe { Marshal.Copy((IntPtr)e.text.text, rawBytes, 0, SDL.SDL_TEXTINPUTEVENT_TEXT_SIZE); }
                    inputHandler.OnTextInput(Encoding.UTF8.GetString(rawBytes, 0, Array.IndexOf(rawBytes, (byte)0)));
                    break;
                }

                case SDL.SDL_EventType.SDL_KEYDOWN:
                case SDL.SDL_EventType.SDL_KEYUP:
                {
                    var keyCode = (Keycode)e.key.keysym.sym;
                    var type    = e.type == SDL.SDL_EventType.SDL_KEYDOWN ?
                                  KeyInputEvent.Down : KeyInputEvent.Up;

                    var tapCount = e.type == SDL.SDL_EventType.SDL_KEYDOWN ?
                                   MultiTapDetection.DetectFromKeyboard(keyCode) :
                                   MultiTapDetection.InfoFromKeyboard(keyCode);

                    var keyEvent = new KeyInput
                    {
                        Event         = type,
                        Key           = keyCode,
                        Modifiers     = mods,
                        UnicodeChar   = (char)e.key.keysym.sym,
                        MultiTapCount = tapCount
                    };

                    // Special case workaround for windows users
                    if (e.key.keysym.sym == SDL.SDL_Keycode.SDLK_F4 && mods.HasModifier(Modifiers.Alt) &&
                        Platform.CurrentPlatform == PlatformType.Windows)
                    {
                        Game.Exit();
                    }
                    else
                    {
                        // Only register initial key press
                        if (e.key.repeat == 0)
                        {
                            inputHandler.OnKeyInput(keyEvent);
                        }
                    }

                    break;
                }
                }
            }

            if (pendingMotion != null)
            {
                inputHandler.OnMouseInput(pendingMotion.Value);
                pendingMotion = null;
            }

            OpenGL.CheckGLError();
        }
Ejemplo n.º 11
0
        public Sdl2GraphicsDevice(Size windowSize, WindowMode windowMode)
        {
            Console.WriteLine("Using SDL 2 with OpenGL renderer");
            WindowSize = windowSize;

            // Disable legacy scaling on Windows
            if (Platform.CurrentPlatform == PlatformType.Windows && !Game.Settings.Graphics.DisableWindowsDPIScaling)
            {
                SetProcessDPIAware();
            }

            SDL.SDL_Init(SDL.SDL_INIT_NOPARACHUTE | SDL.SDL_INIT_VIDEO);
            SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_DOUBLEBUFFER, 1);
            SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_RED_SIZE, 8);
            SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_GREEN_SIZE, 8);
            SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_BLUE_SIZE, 8);
            SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_ALPHA_SIZE, 0);

            SDL.SDL_DisplayMode display;
            SDL.SDL_GetCurrentDisplayMode(0, out display);

            Console.WriteLine("Desktop resolution: {0}x{1}", display.w, display.h);
            if (WindowSize.Width == 0 && WindowSize.Height == 0)
            {
                Console.WriteLine("No custom resolution provided, using desktop resolution");
                WindowSize = new Size(display.w, display.h);
            }

            Console.WriteLine("Using resolution: {0}x{1}", WindowSize.Width, WindowSize.Height);

            var windowFlags = SDL.SDL_WindowFlags.SDL_WINDOW_OPENGL | SDL.SDL_WindowFlags.SDL_WINDOW_ALLOW_HIGHDPI;

            // HiDPI doesn't work properly on OSX with (legacy) fullscreen mode
            if (Platform.CurrentPlatform == PlatformType.OSX && windowMode == WindowMode.Fullscreen)
            {
                SDL.SDL_SetHint(SDL.SDL_HINT_VIDEO_HIGHDPI_DISABLED, "1");
            }

            window = SDL.SDL_CreateWindow("OpenRA", SDL.SDL_WINDOWPOS_CENTERED, SDL.SDL_WINDOWPOS_CENTERED,
                                          WindowSize.Width, WindowSize.Height, windowFlags);

            SurfaceSize = WindowSize;
            WindowScale = 1;

            // Enable high resolution rendering for Retina displays
            if (Platform.CurrentPlatform == PlatformType.OSX)
            {
                // OSX defines the window size in "points", with a device-dependent number of pixels per point.
                // The window scale is simply the ratio of GL pixels / window points.
                int width, height;
                SDL.SDL_GL_GetDrawableSize(window, out width, out height);
                SurfaceSize = new Size(width, height);
                WindowScale = width * 1f / WindowSize.Width;
            }
            else if (Platform.CurrentPlatform == PlatformType.Windows)
            {
                float ddpi, hdpi, vdpi;
                if (!Game.Settings.Graphics.DisableWindowsDPIScaling && SDL.SDL_GetDisplayDPI(0, out ddpi, out hdpi, out vdpi) == 0)
                {
                    WindowScale = ddpi / 96;
                    WindowSize  = new Size((int)(SurfaceSize.Width / WindowScale), (int)(SurfaceSize.Height / WindowScale));
                }
            }
            else
            {
                float scale         = 1;
                var   scaleVariable = Environment.GetEnvironmentVariable("OPENRA_DISPLAY_SCALE");
                if (scaleVariable != null && float.TryParse(scaleVariable, out scale))
                {
                    WindowScale = scale;
                    WindowSize  = new Size((int)(SurfaceSize.Width / WindowScale), (int)(SurfaceSize.Height / WindowScale));
                }
            }

            Console.WriteLine("Using window scale {0:F2}", WindowScale);

            if (Game.Settings.Game.LockMouseWindow)
            {
                GrabWindowMouseFocus();
            }
            else
            {
                ReleaseWindowMouseFocus();
            }

            if (windowMode == WindowMode.Fullscreen)
            {
                SDL.SDL_SetWindowFullscreen(window, (uint)SDL.SDL_WindowFlags.SDL_WINDOW_FULLSCREEN);

                // Fullscreen mode on OSX will ignore the configured display resolution
                // and instead always picks an arbitrary scaled resolution choice that may
                // not match the window size, leading to graphical and input issues.
                // We work around this by force disabling HiDPI and resetting the window and
                // surface sizes to match the size that is forced by SDL.
                // This is usually not what the player wants, but is the best we can consistently do.
                if (Platform.CurrentPlatform == PlatformType.OSX)
                {
                    int width, height;
                    SDL.SDL_GetWindowSize(window, out width, out height);
                    WindowSize  = SurfaceSize = new Size(width, height);
                    WindowScale = 1;
                }
            }
            else if (windowMode == WindowMode.PseudoFullscreen)
            {
                // Work around a visual glitch in OSX: the window is offset
                // partially offscreen if the dock is at the left of the screen
                if (Platform.CurrentPlatform == PlatformType.OSX)
                {
                    SDL.SDL_SetWindowPosition(window, 0, 0);
                }

                SDL.SDL_SetWindowFullscreen(window, (uint)SDL.SDL_WindowFlags.SDL_WINDOW_FULLSCREEN_DESKTOP);
                SDL.SDL_SetHint(SDL.SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0");
            }

            context = SDL.SDL_GL_CreateContext(window);
            if (context == IntPtr.Zero || SDL.SDL_GL_MakeCurrent(window, context) < 0)
            {
                throw new InvalidOperationException("Can not create OpenGL context. (Error: {0})".F(SDL.SDL_GetError()));
            }

            OpenGL.Initialize();

            OpenGL.glEnableVertexAttribArray(Shader.VertexPosAttributeIndex);
            OpenGL.CheckGLError();
            OpenGL.glEnableVertexAttribArray(Shader.TexCoordAttributeIndex);
            OpenGL.CheckGLError();
            OpenGL.glEnableVertexAttribArray(Shader.TexMetadataAttributeIndex);
            OpenGL.CheckGLError();

            SDL.SDL_SetModState(SDL.SDL_Keymod.KMOD_NONE);
            input = new Sdl2Input();
        }