/*
 * Copyright 2013 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.grafika.gles;

import android.opengl.EGL14;
import android.opengl.EGLSurface;
import android.util.Log;

/**
 * Common base class for EGL surfaces.
 * <p>
 * There can be multiple surfaces associated with a single context.
 */
public class EglSurfaceBase
{
	protected static final String TAG = GlUtil.TAG;

	// EglCore object we're associated with.  It may be associated with multiple surfaces.
	EglCore mEglCore;

	private EGLSurface mEGLSurface = EGL14.EGL_NO_SURFACE;
	private int mWidth = -1;
	private int mHeight = -1;

	EglSurfaceBase(EglCore eglCore)
	{
		mEglCore = eglCore;
	}

	/**
	 * Creates a window surface.
	 * <p>
	 *
	 * @param surface May be a Surface or SurfaceTexture.
	 */
	void createWindowSurface(Object surface)
	{
		if (mEGLSurface != EGL14.EGL_NO_SURFACE)
		{
			throw new IllegalStateException("surface already created");
		}
		mEGLSurface = mEglCore.createWindowSurface(surface);

		// Don't cache width/height here, because the size of the underlying surface can change
		// out from under us (see e.g. HardwareScalerActivity).
		//mWidth = mEglCore.querySurface(mEGLSurface, EGL14.EGL_WIDTH);
		//mHeight = mEglCore.querySurface(mEGLSurface, EGL14.EGL_HEIGHT);
	}

	/**
	 * Returns the surface's width, in pixels.
	 * <p>
	 * If this is called on a window surface, and the underlying surface is in the process
	 * of changing size, we may not see the new size right away (e.g. in the "surfaceChanged"
	 * callback).  The size should match after the next buffer swap.
	 */
	public int getWidth()
	{
		if (mWidth < 0)
		{
			return mEglCore.querySurface(mEGLSurface, EGL14.EGL_WIDTH);
		}
		else
		{
			return mWidth;
		}
	}

	/**
	 * Returns the surface's height, in pixels.
	 */
	public int getHeight()
	{
		if (mHeight < 0)
		{
			return mEglCore.querySurface(mEGLSurface, EGL14.EGL_HEIGHT);
		}
		else
		{
			return mHeight;
		}
	}

	/**
	 * Release the EGL surface.
	 */
	public void releaseEglSurface()
	{
		mEglCore.releaseSurface(mEGLSurface);
		mEGLSurface = EGL14.EGL_NO_SURFACE;
		mWidth = mHeight = -1;
	}

	/**
	 * Makes our EGL context and surface current.
	 */
	public void makeCurrent()
	{
		mEglCore.makeCurrent(mEGLSurface);
	}

	/**
	 * Calls eglSwapBuffers.  Use this to "publish" the current frame.
	 *
	 * @return false on failure
	 */
	public boolean swapBuffers()
	{
		boolean result = mEglCore.swapBuffers(mEGLSurface);
		if (!result)
		{
			Log.d(TAG, "WARNING: swapBuffers() failed");
		}
		return result;
	}

	/**
	 * Sends the presentation time stamp to EGL.
	 *
	 * @param nsecs Timestamp, in nanoseconds.
	 */
	public void setPresentationTime(long nsecs)
	{
		mEglCore.setPresentationTime(mEGLSurface, nsecs);
	}
}