Android OpenGLView displays on simulators but not on physical devices

TylerHartwig.4647TylerHartwig.4647 USUniversity ✭✭
edited June 2015 in Xamarin.Forms

Hi all, I have a bit of code here that runs very well on iOS, and in the Android simulator (all is displayed properly). However, I have tried to run it on two different devices (Nexus 5, and SM-P900) both of which will not display the OpenGL render, rather just a black box.

Here is my OpenTK code that is put into the OnDisplay method

using System;
using OpenTK.Graphics.ES20;
using OpenTK.Graphics;
using OpenTK;
using Xamarin.Forms;
using CubeCrack.Shared;
using System.Reflection;
using System.IO;
using System.Collections.Generic;
using System.Diagnostics;
#if __ANDROID__
using Android.Util;
#endif

[assembly: Dependency(typeof(GLEngineShared))]
namespace CubeCrack.Shared
{
    public class GLEngineShared : GLEngine
    {
        uint frameBuffer;
        uint indexBuffer;
        
        uint colorRenderBuffer;
        uint depthRenderBuffer;
        int positionSlot;
        int colorSlot;
        int projectionSlot;
        int modelViewSlot;
        int cubieViewSlot;

        int width_pixels, height_pixels;

        float rotate = 0.0f;
        static readonly float offset = 2.05f;

        public OpenGLView View { get; set; }
        public CubeViewModel ViewModel { get; set; }
        Matrix4 animationMatrix;

        public GLEngineShared () { }

        void SetupRenderBuffers(){
            #if __ANDROID__
            width_pixels = (int)TypedValue.ApplyDimension(ComplexUnitType.Dip, (float) View.Width, Xamarin.Forms.Forms.Context.Resources.DisplayMetrics);
            height_pixels = (int)TypedValue.ApplyDimension(ComplexUnitType.Dip, (float) View.Height, Xamarin.Forms.Forms.Context.Resources.DisplayMetrics);
            Debug.WriteLine("width: " + width_pixels + " height: " + height_pixels);
            #else
            width_pixels = (int)View.Width;
            height_pixels = (int)View.Height;
            #endif
            GL.GenRenderbuffers (1, out depthRenderBuffer);
            GL.BindRenderbuffer (RenderbufferTarget.Renderbuffer, depthRenderBuffer);
            GL.RenderbufferStorage (RenderbufferTarget.Renderbuffer, RenderbufferInternalFormat.DepthComponent16,
                width_pixels, height_pixels);
            
            GL.GenRenderbuffers (1, out colorRenderBuffer);
            GL.BindRenderbuffer (RenderbufferTarget.Renderbuffer, colorRenderBuffer);
            GL.RenderbufferStorage (RenderbufferTarget.Renderbuffer, RenderbufferInternalFormat.Rgba4,
                width_pixels, height_pixels);
        }

        void SetupFrameBuffer(){
            GL.GenFramebuffers (1, out frameBuffer);
            GL.BindFramebuffer (FramebufferTarget.Framebuffer, frameBuffer);
            GL.FramebufferRenderbuffer (FramebufferTarget.Framebuffer, FramebufferSlot.ColorAttachment0,
                RenderbufferTarget.Renderbuffer, colorRenderBuffer);
            GL.FramebufferRenderbuffer (FramebufferTarget.Framebuffer, FramebufferSlot.DepthAttachment,
                RenderbufferTarget.Renderbuffer, depthRenderBuffer);
        }

        int CompileShader(string shaderName, ShaderType shaderType){
            string prefix;
            #if __IOS__
            prefix = "CubeCrack.iOS.";
            #elif __ANDROID__
            prefix = "CubeCrack.Droid.";
            #endif
            var assembly = typeof(GLEngineShared).GetTypeInfo ().Assembly;
            Stream stream = assembly.GetManifestResourceStream (prefix + "Shaders." + shaderName + ".glsl");
            string shaderString;
            using (var reader = new StreamReader (stream)) {
                shaderString = reader.ReadToEnd ();
            }
            int shaderHandle = GL.CreateShader (shaderType);
            GL.ShaderSource (shaderHandle, shaderString);
            GL.CompileShader (shaderHandle);
            return shaderHandle;
        }

        void CompileShaders(){
            int vertexShader = CompileShader ("SimpleVertex", ShaderType.VertexShader);
            int fragmentShader = CompileShader ("SimpleFragment", ShaderType.FragmentShader);
            int programHandle = GL.CreateProgram ();
            GL.AttachShader (programHandle, vertexShader);
            GL.AttachShader (programHandle, fragmentShader);
            GL.LinkProgram (programHandle);
            GL.UseProgram (programHandle);

            positionSlot = GL.GetAttribLocation (programHandle, "Position");
            colorSlot = GL.GetAttribLocation (programHandle, "SourceColor");
            projectionSlot = GL.GetUniformLocation (programHandle, "Projection");
            modelViewSlot = GL.GetUniformLocation (programHandle, "Modelview");
            cubieViewSlot = GL.GetUniformLocation (programHandle, "CubieView");

            GL.EnableVertexAttribArray (positionSlot);
            GL.EnableVertexAttribArray (colorSlot);
        }

        void SetupVBOs(){
            uint vertexBuffer;
            GL.GenBuffers (1, out vertexBuffer);
            GL.BindBuffer (BufferTarget.ArrayBuffer, vertexBuffer);
            GL.BufferData (BufferTarget.ArrayBuffer, (IntPtr)(Vector3.SizeInBytes * CubeData.Verticies.Length), CubeData.Verticies, BufferUsage.StaticDraw);
            GL.VertexAttribPointer (positionSlot, 3, VertexAttribPointerType.Float, false, Vector3.SizeInBytes, 0);



//          GL.GenBuffers (1, out indexBuffer);
//          GL.BindBuffer (BufferTarget.ElementArrayBuffer, indexBuffer);
//          GL.BufferData (BufferTarget.ElementArrayBuffer, (IntPtr)(sizeof(byte) * CubeData.Indices.Length), CubeData.Indices, BufferUsage.StaticDraw);
        }

        #region GLEngine implementation

        public void Initialize ()
        {
//          GL.Viewport (0, 0, (int)View.Width, (int)View.Height);
            SetupRenderBuffers ();
            SetupFrameBuffer ();
            CompileShaders ();
            SetupVBOs ();
        }

        public void DrawCornerCubes(){
            for (int i = 0; i < 8; i++) {
                var colorData = new List ();
                var colors = ViewModel.GetCornerColors (i);
                foreach (var color in colors) {
                    colorData.Add (CubeData.GetVectorFromColor (color));
                }

                var ColorData = new Vector4[24];
                for(int j = 0; j < 24; j++){
                    ColorData[j] = new Vector4(0,0,0,1);
                }
                for(int j = 4; j <= 7; j++){
                    ColorData [j] = colorData [0];
                }
                for(int j = 16; j <= 19; j++){
                    ColorData [j] = colorData [1];
                }
                for (int j = 8; j <= 11; j++) {
                    ColorData [j] = colorData [2];
                }

                uint colorBuffer;
                GL.GenBuffers (1, out colorBuffer);
                GL.BindBuffer (BufferTarget.ArrayBuffer, colorBuffer);
                GL.BufferData (BufferTarget.ArrayBuffer, (IntPtr)(Vector4.SizeInBytes * ColorData.Length), ColorData, BufferUsage.StaticDraw);
                GL.VertexAttribPointer (colorSlot, 4, VertexAttribPointerType.Float, false, Vector4.SizeInBytes, 0);

                Matrix4 animateMatrix;
                if (ViewModel.IsCornerAnimating (i))
                    animateMatrix = animationMatrix;
                else
                    animateMatrix = Matrix4.Identity;
                
                Matrix4 rotationMatrix = Matrix4.CreateRotationX (CubeViewModel.CornerRotationTable [i][0]) *
                                         Matrix4.CreateRotationY (CubeViewModel.CornerRotationTable [i][1]) *
                                         Matrix4.CreateRotationZ (CubeViewModel.CornerRotationTable [i][2]);
                Matrix4 translationMatrix = Matrix4.CreateTranslation (offset * CubeViewModel.CornerTranslationTable [i] [0],
                                                offset * CubeViewModel.CornerTranslationTable [i] [1], offset * CubeViewModel.CornerTranslationTable [i] [2]);
                Matrix4[] cubieView = { rotationMatrix * translationMatrix * animateMatrix };
                GL.UniformMatrix4 (cubieViewSlot, false, ref cubieView [0]);
                GL.DrawElements(BeginMode.Triangles, CubeData.Indices.Length, DrawElementsType.UnsignedByte, CubeData.Indices);
                colorData.Clear ();

                GL.DeleteBuffers (1, ref colorBuffer);
            }
        }

        public void DrawEdgeCubes(){
            for (int i = 0; i < 12; i++) {
                var colorData = new List<Vector4> ();
                var colors = ViewModel.GetEdgeColors (i);
                foreach (var color in colors) {
                    colorData.Add (CubeData.GetVectorFromColor (color));
                }

                var ColorData = new Vector4[24];
                for(int j = 0; j < 24; j++){
                    ColorData[j] = new Vector4(0,0,0,1);
                }
                for(int j = 4; j 

The error I with the Nexus 5 is

[Adreno-EGLSUB] : Invalid native buffer. Failed to queueBuffer
[Adreno-EGLSUB] : native buffer is NULL

And over with my Samsung Note 12.2 (SM-P900)
I noticed this line, which I believe is relevant

[mali_winsys] new_window_surface returns 0x3000

Neither of the applications crash, but just display a black box where I should have OpenGL code rendering.

Any advice on how to debug or find the problem and solution would be much appreciated.

Answers

  • burf2000burf2000 GBMember

    This is now the error I have

  • XavyerXavyer MDMember ✭✭

    Was you able to find a solution for this problem? I think i hit something similar in my project

  • MarkLMarkL GBMember ✭✭

    Did anyone manage to find a solution for this?

    I also have a possible similar issue, however I have narrowed my issue down to being Android devices with Qualcomm processors. Rendering is fine for me on other devices.

    To me it looks like the rendering is trying to do tiling (A feature of the Qualcomm GPU), which is only rendering parts of the view and either incorrectly or not at all depending on the view projection. I see in the OpenTK GL library the extension methods under GL.Qcom... but I have no idea if I should be trying to use them or if it should work normally without and I cannot find any documentation on using them.

    Does anyone have any ideas on this?

  • TylerHartwig.4647TylerHartwig.4647 USUniversity ✭✭

    I have found a solution finally, Android's OpenGL takes care of frame buffers for you, so exclude that code from the android build and you should be alright. Let me know if that doesn't work, and I'll re-check my code for you.

  • MarkLMarkL GBMember ✭✭

    I don't do anything with frame buffers so there's nothing to remove.

  • TylerHartwig.4647TylerHartwig.4647 USUniversity ✭✭

    Do you have the code or sample code you could show me?

  • MarkLMarkL GBMember ✭✭

    Thanks, but I have solved the problem.

    I just added this to my GL initialization function

    GL.Enable((EnableCap)QcomWriteonlyRendering.WriteonlyRenderingQcom);

  • swestrupswestrup Member

    Just leaving a note that the mali_winsys message is a red herring. The return code of 3000 is how egl says everything worked as desired.

Sign In or Register to comment.