blob: 0b3d75c78a7b778e6b04a665f894fadc6128f9d1 [file] [log] [blame]
// 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 client
import (
"net"
"time"
"android.googlesource.com/platform/tools/gpu/atom"
"android.googlesource.com/platform/tools/gpu/binary/schema"
"android.googlesource.com/platform/tools/gpu/log"
"android.googlesource.com/platform/tools/gpu/multiplexer"
"android.googlesource.com/platform/tools/gpu/process"
"android.googlesource.com/platform/tools/gpu/service"
"android.googlesource.com/platform/tools/gpu/service/path"
"github.com/google/gxui"
"github.com/google/gxui/gxfont"
)
const mtu = 1024
var (
rpcResourceRetryDelay = time.Millisecond * 250
)
type ApplicationContext struct {
Config
theme gxui.Theme
monospace gxui.Font
logger *log.Splitter
rpc rpc
dropDownOverlay gxui.BubbleOverlay
toolTipOverlay gxui.BubbleOverlay
toolTipController *gxui.ToolTipController
events Events
atoms []atom.Atom
device *path.Device
constants map[string]schema.ConstantSet
}
func connectServer(config Config) (net.Conn, error) {
args := []string{
"--rpc", config.Gapis,
"--data", config.DataPath,
"--shutdown_on_disconnect",
}
return process.ConnectStartIfNeeded(config.Gapis, "gapis", args...)
}
func CreateApplicationContext(theme gxui.Theme, config Config) (*ApplicationContext, error) {
dropDownOverlay := theme.CreateBubbleOverlay()
toolTipOverlay := theme.CreateBubbleOverlay()
logger := &log.Splitter{}
rpcSocket, err := connectServer(config)
if err != nil {
return nil, err
}
monospace, _ := theme.Driver().CreateFont(gxfont.Monospace, 12)
appCtx := &ApplicationContext{
Config: config,
theme: theme,
monospace: monospace,
logger: logger,
dropDownOverlay: dropDownOverlay,
toolTipOverlay: toolTipOverlay,
toolTipController: gxui.CreateToolTipController(toolTipOverlay, theme.Driver()),
constants: map[string]schema.ConstantSet{},
}
client := service.NewClient(multiplexer.New(rpcSocket, rpcSocket, rpcSocket, mtu, logger, nil), nil)
appCtx.rpc.init(log.Enter(appCtx.logger, "rpc"), client, appCtx.constants)
appCtx.events.Init()
return appCtx, nil
}
// Run enqueues f to be called on the UI go-routine.
// Run can return before f is called.
func (c *ApplicationContext) Run(f func()) bool {
return c.theme.Driver().Call(f)
}
// RunSync calls f on the UI go-routine, blocking until f has returned.
func (c *ApplicationContext) RunSync(f func()) bool {
return c.theme.Driver().CallSync(f)
}
// Change modifies the value at p to v, and selects the new path.
// The call is blocking.
func (c *ApplicationContext) Change(p path.Path, v interface{}) error {
n, err := c.rpc.Change(p, v)
if err != nil {
return err
}
if p != n {
c.events.Select(n)
}
return nil
}