// Copyright (C) 2015 The Android Open Source Project
//
// 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 gles

import (
	"fmt"
	"math/rand"

	"android.googlesource.com/platform/tools/gpu/atom"
	"android.googlesource.com/platform/tools/gpu/binary"
	"android.googlesource.com/platform/tools/gpu/database"
	"android.googlesource.com/platform/tools/gpu/gfxapi"
	"android.googlesource.com/platform/tools/gpu/log"
	"android.googlesource.com/platform/tools/gpu/memory"
	"android.googlesource.com/platform/tools/gpu/replay"
	"android.googlesource.com/platform/tools/gpu/replay/builder"
	"android.googlesource.com/platform/tools/gpu/replay/value"
)

func readFramebufferDepth(out chan replay.Image) atom.Atom {
	return replay.Custom(func(i atom.ID, s *gfxapi.State, d database.Database, l log.Logger, b *builder.Builder) error {
		arch := s.Architecture
		c := getContext(s)

		colorW, colorH, err := getState(s).getFramebufferAttachmentSize(gfxapi.FramebufferAttachmentColor)
		if err != nil {
			return err
		}
		depthW, depthH, err := getState(s).getFramebufferAttachmentSize(gfxapi.FramebufferAttachmentDepth)
		if err != nil {
			return err
		}

		const (
			uTextureLocation      UniformLocation   = 0
			aScreenCoordsLocation AttributeLocation = 0

			vertexShaderSource string = `
				precision highp float;
				attribute vec2 aScreenCoords;
				varying vec2 vTexCoords;

				void main() {
					vTexCoords = aScreenCoords / 2. + vec2(0.5, 0.5);
					gl_Position = vec4(aScreenCoords.xy, 0., 1.);
				}`
			fragmentShaderSource string = `
				precision highp float;
				uniform sampler2D uTexture;
				varying vec2 vTexCoords;

				vec4 float2rgba(float f) {
					vec4 v = fract(f * vec4(1., 255., 65025., 16581375.));
					return v - vec4(v.yzw, 0.) / 255.;
				}

				void main() {
					float sample = texture2D(uTexture, vTexCoords).r;
					gl_FragColor = float2rgba(sample);
				}`
		)

		var (
			origProgramID            = c.BoundProgram
			origRenderbufferID       = c.BoundRenderbuffers[GLenum_GL_RENDERBUFFER]
			origReadFramebufferID    = c.BoundFramebuffers[GLenum_GL_READ_FRAMEBUFFER]
			origDrawFramebufferID    = c.BoundFramebuffers[GLenum_GL_DRAW_FRAMEBUFFER]
			origTextureID            = c.TextureUnits[c.ActiveTextureUnit][GLenum_GL_TEXTURE_2D]
			origArrayBufferID        = c.BoundBuffers[GLenum_GL_ARRAY_BUFFER]
			origElementArrayBufferID = c.BoundBuffers[GLenum_GL_ELEMENT_ARRAY_BUFFER]
			origActiveTextureUnit    = int32(c.ActiveTextureUnit - GLenum_GL_TEXTURE0)

			inW  = int32(depthW)
			inH  = int32(depthH)
			outW = int32(colorW)
			outH = int32(colorH)
		)

		// Generate new unused object IDs.
		renderbufferID := RenderbufferId(newUnusedID(func(x uint32) bool { _, ok := c.Instances.Renderbuffers[RenderbufferId(x)]; return ok }))
		framebufferID := FramebufferId(newUnusedID(func(x uint32) bool { _, ok := c.Instances.Framebuffers[FramebufferId(x)]; return ok }))
		textureID := TextureId(newUnusedID(func(x uint32) bool { _, ok := c.Instances.Textures[TextureId(x)]; return ok }))
		programID := ProgramId(newUnusedID(func(x uint32) bool { _, ok := c.Instances.Programs[ProgramId(x)]; return ok }))
		vertexShaderID := ShaderId(newUnusedID(func(x uint32) bool { _, ok := c.Instances.Shaders[ShaderId(x)]; return ok }))
		fragmentShaderID := ShaderId(newUnusedID(func(x uint32) bool {
			_, ok := c.Instances.Shaders[ShaderId(x)]
			return ok || ShaderId(x) == vertexShaderID
		}))

		// 2D vertices positions for a full screen 2D triangle strip.
		positions := []float32{-1., -1., 1., -1., -1., 1., 1., 1.}

		// Temporarily change rasterizing/blending state and enable VAP 0.
		undoList := []atom.Atom{}
		for _, cap := range []GLenum{
			GLenum_GL_BLEND,
			GLenum_GL_CULL_FACE,
			GLenum_GL_DEPTH_TEST,
			GLenum_GL_SCISSOR_TEST,
			GLenum_GL_STENCIL_TEST,
		} {
			capability := cap
			if c.Capabilities[capability] {
				NewGlDisable(capability).Replay(i, s, d, l, b)
				undoList = append(undoList, NewGlEnable(capability))
			}
		}
		if !c.VertexAttributeArrays[aScreenCoordsLocation].Enabled {
			NewGlEnableVertexAttribArray(aScreenCoordsLocation).Replay(i, s, d, l, b)
			undoList = append(undoList, NewGlDisableVertexAttribArray(aScreenCoordsLocation))
		}

		replayEach(i, s, d, l, b,
			// Setup new framebuffer/renderbuffer.
			NewGlGenFramebuffers(1, memory.Tmp).
				AddRead(atom.Data(arch, d, l, memory.Tmp, framebufferID)),
			NewGlBindFramebuffer(GLenum_GL_DRAW_FRAMEBUFFER, framebufferID),
			NewGlGenRenderbuffers(1, memory.Tmp).
				AddRead(atom.Data(arch, d, l, memory.Tmp, renderbufferID)),
			NewGlBindRenderbuffer(GLenum_GL_RENDERBUFFER, renderbufferID),
			NewGlRenderbufferStorage(GLenum_GL_RENDERBUFFER, GLenum_GL_RGBA8, GLsizei(outW), GLsizei(outH)),
			NewGlFramebufferRenderbuffer(GLenum_GL_DRAW_FRAMEBUFFER, GLenum_GL_COLOR_ATTACHMENT0, GLenum_GL_RENDERBUFFER, renderbufferID),

			// Setup depth texture.
			NewGlGenTextures(1, memory.Tmp).
				AddRead(atom.Data(arch, d, l, memory.Tmp, textureID)),
			NewGlBindTexture(GLenum_GL_TEXTURE_2D, textureID),
			NewGlTexImage2D(GLenum_GL_TEXTURE_2D, 0, GLint(GLenum_GL_DEPTH24_STENCIL8), GLsizei(outW), GLsizei(outH), 0, GLenum_GL_DEPTH_STENCIL, GLenum_GL_UNSIGNED_INT_24_8, memory.Nullptr),
			NewGlTexParameteri(GLenum_GL_TEXTURE_2D, GLenum_GL_TEXTURE_MIN_FILTER, GLint(GLenum_GL_NEAREST)),
			NewGlTexParameteri(GLenum_GL_TEXTURE_2D, GLenum_GL_TEXTURE_MAG_FILTER, GLint(GLenum_GL_NEAREST)),
			NewGlTexParameteri(GLenum_GL_TEXTURE_2D, GLenum_GL_TEXTURE_WRAP_S, GLint(GLenum_GL_CLAMP_TO_EDGE)),
			NewGlTexParameteri(GLenum_GL_TEXTURE_2D, GLenum_GL_TEXTURE_WRAP_T, GLint(GLenum_GL_CLAMP_TO_EDGE)),

			// Blit depth attachment.
			NewGlFramebufferTexture2D(GLenum_GL_DRAW_FRAMEBUFFER, GLenum_GL_DEPTH_ATTACHMENT, GLenum_GL_TEXTURE_2D, textureID, 0),
			NewGlBlitFramebuffer(0, 0, GLint(inW), GLint(inH), 0, 0, GLint(outW), GLint(outH), GLbitfield_GL_DEPTH_BUFFER_BIT, GLenum_GL_NEAREST),
			NewGlFramebufferTexture2D(GLenum_GL_DRAW_FRAMEBUFFER, GLenum_GL_DEPTH_ATTACHMENT, GLenum_GL_TEXTURE_2D, TextureId(0), 0),

			// Bind new framebuffer.
			NewGlBindFramebuffer(GLenum_GL_READ_FRAMEBUFFER, framebufferID),

			// Render depth texture to framebuffer color attachment.
			NewGlClear(GLbitfield_GL_COLOR_BUFFER_BIT),
		)

		// Create the shader program
		replayEach(i, s, d, l, b,
			NewProgram(arch, d, l, vertexShaderID, fragmentShaderID, programID, vertexShaderSource, fragmentShaderSource)...)

		replayEach(i, s, d, l, b,
			NewGlBindAttribLocation(programID, aScreenCoordsLocation, "aScreenCoords"),
			NewGlLinkProgram(programID),
			NewGlUseProgram(programID),
			NewGlBindTexture(GLenum_GL_TEXTURE_2D, textureID),
			NewGlGetUniformLocation(programID, "uTexture", uTextureLocation),
			NewGlUniform1i(uTextureLocation, GLint(origActiveTextureUnit)),
			NewGlBindBuffer(GLenum_GL_ARRAY_BUFFER, 0),
			NewGlBindBuffer(GLenum_GL_ELEMENT_ARRAY_BUFFER, 0),
			NewGlVertexAttribPointer(aScreenCoordsLocation, 2, GLenum_GL_FLOAT, false, 0, memory.Tmp),
			NewGlDrawArrays(GLenum_GL_TRIANGLE_STRIP, 0, 4).
				AddRead(atom.Data(arch, d, l, memory.Tmp, positions)),
		)

		postColorData(i, s, d, l, b, outW, outH, out)

		// Restore conditionally changed state.
		replayEach(i, s, d, l, b, undoList...)

		replayEach(i, s, d, l, b,
			// Restore buffer/vertexAttrib state.
			NewGlBindBuffer(GLenum_GL_ELEMENT_ARRAY_BUFFER, origElementArrayBufferID),
			NewGlBindBuffer(GLenum_GL_ARRAY_BUFFER, origArrayBufferID),
			// Note: we're not restoring the original VertexAttribPointer as we may re-enter an inconsistent state, which would abort the current replay batch.
			// NewGlVertexAttribPointer(aScreenCoordsLocation, origVertexAttrib.Size, origVertexAttrib.Type, origVertexAttrib.Normalized, origVertexAttrib.Stride, VertexPointer(origVertexAttrib.Data)),

			// Restore texture state.
			NewGlBindTexture(GLenum_GL_TEXTURE_2D, origTextureID),
			NewGlDeleteTextures(1, memory.Tmp).
				AddRead(atom.Data(arch, d, l, memory.Tmp, textureID)),

			// Restore framebuffer/renderbuffer state.
			NewGlBindRenderbuffer(GLenum_GL_RENDERBUFFER, origRenderbufferID),
			NewGlBindFramebuffer(GLenum_GL_READ_FRAMEBUFFER, origReadFramebufferID),
			NewGlBindFramebuffer(GLenum_GL_DRAW_FRAMEBUFFER, origDrawFramebufferID),
			NewGlDeleteRenderbuffers(1, memory.Tmp).
				AddRead(atom.Data(arch, d, l, memory.Tmp, renderbufferID)),
			NewGlDeleteFramebuffers(1, memory.Tmp).
				AddRead(atom.Data(arch, d, l, memory.Tmp, framebufferID)),

			// Restore program state.
			NewGlUseProgram(origProgramID),
			NewGlDeleteProgram(programID),
			NewGlDeleteShader(vertexShaderID),
			NewGlDeleteShader(fragmentShaderID),
		)

		return nil
	})
}

func readFramebufferColor(width, height uint32, out chan replay.Image) atom.Atom {
	return replay.Custom(func(i atom.ID, s *gfxapi.State, d database.Database, l log.Logger, b *builder.Builder) error {
		arch := s.Architecture
		c := getContext(s)

		colorW, colorH, err := getState(s).getFramebufferAttachmentSize(gfxapi.FramebufferAttachmentColor)
		if err != nil {
			return err
		}

		var (
			origRenderbufferID    = c.BoundRenderbuffers[GLenum_GL_RENDERBUFFER]
			origReadFramebufferID = c.BoundFramebuffers[GLenum_GL_READ_FRAMEBUFFER]
			origDrawFramebufferID = c.BoundFramebuffers[GLenum_GL_DRAW_FRAMEBUFFER]

			inW  = int32(colorW)
			inH  = int32(colorH)
			outW = int32(width)
			outH = int32(height)
		)

		// Generate new unused object IDs.
		renderbufferID := RenderbufferId(newUnusedID(func(x uint32) bool { _, ok := c.Instances.Renderbuffers[RenderbufferId(x)]; return ok }))
		framebufferID := FramebufferId(newUnusedID(func(x uint32) bool { _, ok := c.Instances.Framebuffers[FramebufferId(x)]; return ok }))

		if inW == outW && inH == outH {
			postColorData(i, s, d, l, b, outW, outH, out)
		} else {
			ctx := getContext(s)
			origScissor := ctx.Rasterizing.Scissor

			replayEach(i, s, d, l, b,
				NewGlScissor(0, 0, GLsizei(colorW), GLsizei(colorH)),
				NewGlGenFramebuffers(1, memory.Tmp).
					AddRead(atom.Data(arch, d, l, memory.Tmp, framebufferID)),
				NewGlBindFramebuffer(GLenum_GL_DRAW_FRAMEBUFFER, framebufferID),
				NewGlGenRenderbuffers(1, memory.Tmp).
					AddRead(atom.Data(arch, d, l, memory.Tmp, renderbufferID)),
				NewGlBindRenderbuffer(GLenum_GL_RENDERBUFFER, renderbufferID),
				NewGlRenderbufferStorage(GLenum_GL_RENDERBUFFER, GLenum_GL_RGBA8, GLsizei(outW), GLsizei(outH)),
				NewGlFramebufferRenderbuffer(GLenum_GL_DRAW_FRAMEBUFFER, GLenum_GL_COLOR_ATTACHMENT0, GLenum_GL_RENDERBUFFER, renderbufferID),
				NewGlBlitFramebuffer(0, 0, GLint(inW), GLint(inH), 0, 0, GLint(outW), GLint(outH), GLbitfield_GL_COLOR_BUFFER_BIT, GLenum_GL_LINEAR),
				NewGlBindFramebuffer(GLenum_GL_READ_FRAMEBUFFER, framebufferID),
			)

			postColorData(i, s, d, l, b, outW, outH, out)

			replayEach(i, s, d, l, b,
				NewGlBindRenderbuffer(GLenum_GL_RENDERBUFFER, origRenderbufferID),
				NewGlBindFramebuffer(GLenum_GL_READ_FRAMEBUFFER, origReadFramebufferID),
				NewGlBindFramebuffer(GLenum_GL_DRAW_FRAMEBUFFER, origDrawFramebufferID),
				NewGlDeleteRenderbuffers(1, memory.Tmp).
					AddRead(atom.Data(arch, d, l, memory.Tmp, renderbufferID)),
				NewGlDeleteFramebuffers(1, memory.Tmp).
					AddRead(atom.Data(arch, d, l, memory.Tmp, framebufferID)),
				NewGlScissor(origScissor.X, origScissor.Y, origScissor.Width, origScissor.Height),
			)
		}

		return nil
	})
}

func postColorData(i atom.ID, s *gfxapi.State, d database.Database, l log.Logger, b *builder.Builder, width, height int32, img chan<- replay.Image) {
	ctx := getContext(s)
	origPackAlignment := ctx.PixelStorage[GLenum_GL_PACK_ALIGNMENT]
	if origPackAlignment != 1 {
		NewGlPixelStorei(GLenum_GL_PACK_ALIGNMENT, 1).Replay(i, s, d, l, b)
		defer NewGlPixelStorei(GLenum_GL_PACK_ALIGNMENT, origPackAlignment).Replay(i, s, d, l, b)
	}
	if origPackBuffer, ok := ctx.BoundBuffers[GLenum_GL_PIXEL_PACK_BUFFER]; ok && origPackBuffer != 0 {
		NewGlBindBuffer(GLenum_GL_PIXEL_PACK_BUFFER, 0).Replay(i, s, d, l, b)
		defer NewGlBindBuffer(GLenum_GL_PIXEL_PACK_BUFFER, origPackBuffer).Replay(i, s, d, l, b)
	}

	imageSize := uint64(width * height * 4)
	NewGlReadPixels(0, 0, GLsizei(width), GLsizei(height), GLenum_GL_RGBA, GLenum_GL_UNSIGNED_BYTE, memory.Tmp).Replay(i, s, d, l, b)
	b.Post(value.RemappedPointer(memory.Tmp.Address), imageSize, func(d binary.Decoder, err error) error {
		var data []byte
		if err == nil {
			data = make([]byte, imageSize)
			err = d.Data(data)
		}
		if err != nil {
			err = fmt.Errorf("Could not read framebuffer data (expected length %d bytes): %v", imageSize, err)
			data = nil
		}
		img <- replay.Image{Data: data, Error: err}
		return err
	})
}

func replayEach(i atom.ID, s *gfxapi.State, d database.Database, l log.Logger, b *builder.Builder, atoms ...atom.Atom) {
	for _, a := range atoms {
		if r, ok := a.(replay.Replayer); ok {
			r.Replay(i, s, d, l, b)
		}
	}
}

func newUnusedID(existenceTest func(uint32) bool) uint32 {
	for {
		x := rand.Uint32()
		if !existenceTest(x) {
			return x
		}
	}
}
