How can I get the Wisth and Height of the GLSurfaceView I am currently render in, in pixels?
may be this:
#Override
public void onSurfaceChanged(GL10 glUnused, int width, int height) {
}
of
public class MyGLRenderer implements GLSurfaceView.Renderer
Related
I wanted to know if it is possible to use SurfaceHolder.Callback (and of course its callbacks) in combination with TextureView?
I mean sth. like the following:
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback {
private TextureView mTextureView;
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
}
}
Would that be working? The reason I ask is that whenever I see SurfaceHolder.Callback, they use SurfaceView.
No you can't. For TextureView you should use SurfaceTextureListener. In many senses these callbacks are similar to SurfaceHolder callbacks.
For example, instead of
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mPreviewSurface = holder.getSurface();
}
you can write
#Override
public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) {
mPreviewSurface = new Surface(texture);
}
See https://github.com/google/ExoPlayer/issues/98. Thanks to #BrentM.
I am trying for weeks to render a vlc streaming to OpenGL on Android.
I guess I am missing something. Here is what I have so far.
This is my custom class:
public class VLCVideoView extends SurfaceView implements SurfaceHolder.Callback, IVideoPlayer, GLSurfaceView.Renderer
My initialization on VLC:
try {
// Create a new media player
libvlc = LibVLC.getInstance();
libvlc.setHardwareAcceleration(LibVLC.HW_ACCELERATION_FULL);
libvlc.eventVideoPlayerActivityCreated(true);
libvlc.setSubtitlesEncoding("");
libvlc.setAout(LibVLC.AOUT_OPENSLES);
libvlc.setVout(LibVLC.VOUT_OPEGLES2);
//libvlc.setVout(LibVLC.VOUT_ANDROID_SURFACE);
libvlc.setTimeStretching(true);
libvlc.setChroma("RV32");
libvlc.setVerboseMode(true);
LibVLC.restart(context);
holder.setFormat(PixelFormat.RGBA_8888);
mSurface = holder.getSurface();
libvlc.attachSurface(mSurface, this);
Implemented the entire GLSurfaceView.Renderer methods:
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config)
#Override
public void onSurfaceChanged(GL10 gl, int width, int height)
#Override
public void onDrawFrame(GL10 gl)
As well, as:
#Override
protected void onDraw(Canvas canvas) for the VLCVideoView
{
if (mSurface!= null)
{
try {
Canvas surfaceCanvas = mSurface.lockCanvas(null);
if(surfaceCanvas != null)
{
super.onDraw(surfaceCanvas);
mSurface.unlockCanvasAndPost(surfaceCanvas);
}
} catch (Surface.OutOfResourcesException excp) {
excp.printStackTrace();
}
}
}
I have a rotating cube being draw, but instead of having the streaming frames as textures, it simple appears streaming on a flat surface.
Any clue?
I want to learn how to use OpenGL for Android. Therefore I followed this guide to set up the environment.
I have done everything like they say:
I got a OpenGLActivity which initiates my MyGLSurfaceView:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
glSurfaceView = new MyGLSurfaceView(this);
setContentView(R.layout.activity_open_gl);
}
This is my MyGLSurfaceView:
class MyGLSurfaceView extends GLSurfaceView {
private final MyGLRenderer mRenderer;
public MyGLSurfaceView(Context context) {
super(context);
// Create an OpenGL ES 2.0 context
setEGLContextClientVersion(2);
mRenderer = new MyGLRenderer();
// Set the Renderer for drawing on the GLSurfaceView
setRenderer(mRenderer);
}
}
And Thats my MyGLRenderder class which should set the background to black:
public class MyGLRenderer implements Renderer {
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
// Set the background frame color
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}
public void onDrawFrame(GL10 unused) {
// Redraw background color
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
}
public void onSurfaceChanged(GL10 unused, int width, int height) {
GLES20.glViewport(0, 0, width, height);
}
}
And I've added this line to my AndroidManifest.xml (right at the beginning, before <application> tag)
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
The problem is that the background isn't black, its white.
Am I missing something?
You're not actually displaying your OpenGL view. In this code here:
glSurfaceView = new MyGLSurfaceView(this);
setContentView(R.layout.activity_open_gl);
you're setting the content view to be a view from your layout, while you're not using the GLSurfaceView you just created. It should be:
glSurfaceView = new MyGLSurfaceView(this);
setContentView(glSurfaceView);
I'm implementing the GLSurfaceView.Renderer like so:
public class GL20Renderer implements GLSurfaceView.Renderer {
private static GL20Renderer mInstance = new GL20Renderer();
private GL20Renderer() {}
public static GL20Renderer getInstance() {
return mInstance;
}
#Override
public void onDrawFrame(GL10 gl) {
Log.e("App", "onDrawFrame()");
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
Log.e("App", "onSurfaceChanged()");
}
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
Log.e("App", "onSurfaceCreated()");
}
}
This class is implemented in the MainActivity:
public class MainActivity extends Activity {
private GLSurfaceView mGLView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
// Create a GLSurfaceView instance and set it as the ContentView for this Activity
mGLView = new GL20SurfaceView(this);
setContentView(mGLView);
}
#Override
protected void onPause() {
super.onPause();
mGLView.onPause();
}
#Override
protected void onResume() {
super.onResume();
mGLView.onResume();
}
}
GL20SurfaceView is:
public class GL20SurfaceView extends GLSurfaceView {
public GL20SurfaceView(Context context) {
super(context);
// Create an OpenGL ES 2.0 context.
setEGLContextClientVersion(2);
// Set the Renderer for drawing on the GLSurfaceView
setRenderer(GL20Renderer.getInstance());
}
}
Very simple as you can see.
When I now start the App, the onSurfaceCreated() method is correctly called, follow by one call of onSurfaceChanged().
Problem now is: Whenever the device orientation changes, I get another call of onSurfaceCreated() followed by onSurfaceChanged().
In my understanding, the onSurfaceCreated() method is called whenever a new surface needs to be created. My question is: Why does it do that whenever I change just the device orientation? Shouldn't it be sufficient that only a onSurfaceChanged() call is triggered in order to adjust the viewport?
Note that I don't put my device to sleep when changing the orientation.
DO this way
<activity
android:name=".MainActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
/>
The one of advantages of OpenGL that you draw regards to screen size. It gives you ability to handle all Android resolutions.
I'm not sure how it works with GL20 (sure the same like GL10).
As I know in onSurfaceChanged provides several configurations for OpenGL based on length/width of your screen.
For example glViewport
It is necessary to call glViewport handler when GL view dimensions are modified.
Only if you have width = height is unnecessary but its other story.
as exampe
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
// prevent 0 divide
if(height == 0) {
height=1;
}
screenWidth = width;
screenHeight = height;
ratio = (float) width/height;
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glOrthof(0, width, 0, height, -10f, 10f);
gl.glViewport(0, 0, screenWidth, screenHeight);
If you want to avoid that, add to Manifest.xml:
<activity android:name="Activity"
android:configChanges="screenSize|orientation">
I'm experiencing a nullpointerexception in my android java code in the following code. This is inside AndroidGraphics.java.
public void drawPixmap(Pixmap pixmap, int x, int y) {
canvas.drawBitmap(((AndroidPixmap)pixmap).bitmap, x, y, null);
}
AndroidPixmap.java is here:
package com.badlogic.androidgames.framework.impl;
import android.graphics.Bitmap;
import com.badlogic.androidgames.framework.Graphics.PixmapFormat;
import com.badlogic.androidgames.framework.Pixmap;
public class AndroidPixmap implements Pixmap{
Bitmap bitmap;
PixmapFormat format;
public AndroidPixmap(Bitmap bitmap, PixmapFormat format){
this.bitmap = bitmap;
this.format = format;
}
#Override
public int getWidth(){
return bitmap.getWidth();
}
#Override
public int getHeight(){
return bitmap.getHeight();
}
#Override
public PixmapFormat getFormat(){
return format;
}
#Override
public void dispose(){
bitmap.recycle();
}
}
Is there something wrong with the casting? Any help would be great!
EDIT: This is the pixmap class:
package com.badlogic.androidgames.framework;
import com.badlogic.androidgames.framework.Graphics.PixmapFormat;
public interface Pixmap {
public int getWidth();
public int getHeight();
public PixmapFormat getFormat();
public void dispose();
}
Your AndroidPixmap implements Pixmap, it is not inherited/extended from Pixmap. If you cast to Pixmap, you get the Implementation only, which I assume has bitmap=null.
As you didn't add the Pixmap class to the question, it's quite hard to answer in more detail.
Try this:
public void drawPixmap(AndroidPixmap pixmap, int x, int y) {
canvas.drawBitmap(pixmap.bitmap, x, y, null);
}
Alternatively if you want to keep Pixmap in the signature you can make it an abstract class and extend it instead of an interface.