// Package dri2 is the X client API for the DRI2 extension.
package dri2

// This file is automatically generated from dri2.xml. Edit at your peril!

import (
	"github.com/BurntSushi/xgb"

	"github.com/BurntSushi/xgb/xproto"
)

// Init must be called before using the DRI2 extension.
func Init(c *xgb.Conn) error {
	reply, err := xproto.QueryExtension(c, 4, "DRI2").Reply()
	switch {
	case err != nil:
		return err
	case !reply.Present:
		return xgb.Errorf("No extension named DRI2 could be found on on the server.")
	}

	c.ExtLock.Lock()
	c.Extensions["DRI2"] = reply.MajorOpcode
	c.ExtLock.Unlock()
	for evNum, fun := range xgb.NewExtEventFuncs["DRI2"] {
		xgb.NewEventFuncs[int(reply.FirstEvent)+evNum] = fun
	}
	for errNum, fun := range xgb.NewExtErrorFuncs["DRI2"] {
		xgb.NewErrorFuncs[int(reply.FirstError)+errNum] = fun
	}
	return nil
}

func init() {
	xgb.NewExtEventFuncs["DRI2"] = make(map[int]xgb.NewEventFun)
	xgb.NewExtErrorFuncs["DRI2"] = make(map[int]xgb.NewErrorFun)
}

type AttachFormat struct {
	Attachment uint32
	Format     uint32
}

// AttachFormatRead reads a byte slice into a AttachFormat value.
func AttachFormatRead(buf []byte, v *AttachFormat) int {
	b := 0

	v.Attachment = xgb.Get32(buf[b:])
	b += 4

	v.Format = xgb.Get32(buf[b:])
	b += 4

	return b
}

// AttachFormatReadList reads a byte slice into a list of AttachFormat values.
func AttachFormatReadList(buf []byte, dest []AttachFormat) int {
	b := 0
	for i := 0; i < len(dest); i++ {
		dest[i] = AttachFormat{}
		b += AttachFormatRead(buf[b:], &dest[i])
	}
	return xgb.Pad(b)
}

// Bytes writes a AttachFormat value to a byte slice.
func (v AttachFormat) Bytes() []byte {
	buf := make([]byte, 8)
	b := 0

	xgb.Put32(buf[b:], v.Attachment)
	b += 4

	xgb.Put32(buf[b:], v.Format)
	b += 4

	return buf[:b]
}

// AttachFormatListBytes writes a list of AttachFormat values to a byte slice.
func AttachFormatListBytes(buf []byte, list []AttachFormat) int {
	b := 0
	var structBytes []byte
	for _, item := range list {
		structBytes = item.Bytes()
		copy(buf[b:], structBytes)
		b += len(structBytes)
	}
	return xgb.Pad(b)
}

const (
	AttachmentBufferFrontLeft      = 0
	AttachmentBufferBackLeft       = 1
	AttachmentBufferFrontRight     = 2
	AttachmentBufferBackRight      = 3
	AttachmentBufferDepth          = 4
	AttachmentBufferStencil        = 5
	AttachmentBufferAccum          = 6
	AttachmentBufferFakeFrontLeft  = 7
	AttachmentBufferFakeFrontRight = 8
	AttachmentBufferDepthStencil   = 9
	AttachmentBufferHiz            = 10
)

// BufferSwapComplete is the event number for a BufferSwapCompleteEvent.
const BufferSwapComplete = 0

type BufferSwapCompleteEvent struct {
	Sequence uint16
	// padding: 1 bytes
	EventType uint16
	// padding: 2 bytes
	Drawable xproto.Drawable
	UstHi    uint32
	UstLo    uint32
	MscHi    uint32
	MscLo    uint32
	Sbc      uint32
}

// BufferSwapCompleteEventNew constructs a BufferSwapCompleteEvent value that implements xgb.Event from a byte slice.
func BufferSwapCompleteEventNew(buf []byte) xgb.Event {
	v := BufferSwapCompleteEvent{}
	b := 1 // don't read event number

	b += 1 // padding

	v.Sequence = xgb.Get16(buf[b:])
	b += 2

	v.EventType = xgb.Get16(buf[b:])
	b += 2

	b += 2 // padding

	v.Drawable = xproto.Drawable(xgb.Get32(buf[b:]))
	b += 4

	v.UstHi = xgb.Get32(buf[b:])
	b += 4

	v.UstLo = xgb.Get32(buf[b:])
	b += 4

	v.MscHi = xgb.Get32(buf[b:])
	b += 4

	v.MscLo = xgb.Get32(buf[b:])
	b += 4

	v.Sbc = xgb.Get32(buf[b:])
	b += 4

	return v
}

// Bytes writes a BufferSwapCompleteEvent value to a byte slice.
func (v BufferSwapCompleteEvent) Bytes() []byte {
	buf := make([]byte, 32)
	b := 0

	// write event number
	buf[b] = 0
	b += 1

	b += 1 // padding

	b += 2 // skip sequence number

	xgb.Put16(buf[b:], v.EventType)
	b += 2

	b += 2 // padding

	xgb.Put32(buf[b:], uint32(v.Drawable))
	b += 4

	xgb.Put32(buf[b:], v.UstHi)
	b += 4

	xgb.Put32(buf[b:], v.UstLo)
	b += 4

	xgb.Put32(buf[b:], v.MscHi)
	b += 4

	xgb.Put32(buf[b:], v.MscLo)
	b += 4

	xgb.Put32(buf[b:], v.Sbc)
	b += 4

	return buf
}

// SequenceId returns the sequence id attached to the BufferSwapComplete event.
// Events without a sequence number (KeymapNotify) return 0.
// This is mostly used internally.
func (v BufferSwapCompleteEvent) SequenceId() uint16 {
	return v.Sequence
}

// String is a rudimentary string representation of BufferSwapCompleteEvent.
func (v BufferSwapCompleteEvent) String() string {
	fieldVals := make([]string, 0, 9)
	fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence))
	fieldVals = append(fieldVals, xgb.Sprintf("EventType: %d", v.EventType))
	fieldVals = append(fieldVals, xgb.Sprintf("Drawable: %d", v.Drawable))
	fieldVals = append(fieldVals, xgb.Sprintf("UstHi: %d", v.UstHi))
	fieldVals = append(fieldVals, xgb.Sprintf("UstLo: %d", v.UstLo))
	fieldVals = append(fieldVals, xgb.Sprintf("MscHi: %d", v.MscHi))
	fieldVals = append(fieldVals, xgb.Sprintf("MscLo: %d", v.MscLo))
	fieldVals = append(fieldVals, xgb.Sprintf("Sbc: %d", v.Sbc))
	return "BufferSwapComplete {" + xgb.StringsJoin(fieldVals, ", ") + "}"
}

func init() {
	xgb.NewExtEventFuncs["DRI2"][0] = BufferSwapCompleteEventNew
}

type DRI2Buffer struct {
	Attachment uint32
	Name       uint32
	Pitch      uint32
	Cpp        uint32
	Flags      uint32
}

// DRI2BufferRead reads a byte slice into a DRI2Buffer value.
func DRI2BufferRead(buf []byte, v *DRI2Buffer) int {
	b := 0

	v.Attachment = xgb.Get32(buf[b:])
	b += 4

	v.Name = xgb.Get32(buf[b:])
	b += 4

	v.Pitch = xgb.Get32(buf[b:])
	b += 4

	v.Cpp = xgb.Get32(buf[b:])
	b += 4

	v.Flags = xgb.Get32(buf[b:])
	b += 4

	return b
}

// DRI2BufferReadList reads a byte slice into a list of DRI2Buffer values.
func DRI2BufferReadList(buf []byte, dest []DRI2Buffer) int {
	b := 0
	for i := 0; i < len(dest); i++ {
		dest[i] = DRI2Buffer{}
		b += DRI2BufferRead(buf[b:], &dest[i])
	}
	return xgb.Pad(b)
}

// Bytes writes a DRI2Buffer value to a byte slice.
func (v DRI2Buffer) Bytes() []byte {
	buf := make([]byte, 20)
	b := 0

	xgb.Put32(buf[b:], v.Attachment)
	b += 4

	xgb.Put32(buf[b:], v.Name)
	b += 4

	xgb.Put32(buf[b:], v.Pitch)
	b += 4

	xgb.Put32(buf[b:], v.Cpp)
	b += 4

	xgb.Put32(buf[b:], v.Flags)
	b += 4

	return buf[:b]
}

// DRI2BufferListBytes writes a list of DRI2Buffer values to a byte slice.
func DRI2BufferListBytes(buf []byte, list []DRI2Buffer) int {
	b := 0
	var structBytes []byte
	for _, item := range list {
		structBytes = item.Bytes()
		copy(buf[b:], structBytes)
		b += len(structBytes)
	}
	return xgb.Pad(b)
}

const (
	DriverTypeDri   = 0
	DriverTypeVdpau = 1
)

const (
	EventTypeExchangeComplete = 1
	EventTypeBlitComplete     = 2
	EventTypeFlipComplete     = 3
)

// InvalidateBuffers is the event number for a InvalidateBuffersEvent.
const InvalidateBuffers = 1

type InvalidateBuffersEvent struct {
	Sequence uint16
	// padding: 1 bytes
	Drawable xproto.Drawable
}

// InvalidateBuffersEventNew constructs a InvalidateBuffersEvent value that implements xgb.Event from a byte slice.
func InvalidateBuffersEventNew(buf []byte) xgb.Event {
	v := InvalidateBuffersEvent{}
	b := 1 // don't read event number

	b += 1 // padding

	v.Sequence = xgb.Get16(buf[b:])
	b += 2

	v.Drawable = xproto.Drawable(xgb.Get32(buf[b:]))
	b += 4

	return v
}

// Bytes writes a InvalidateBuffersEvent value to a byte slice.
func (v InvalidateBuffersEvent) Bytes() []byte {
	buf := make([]byte, 32)
	b := 0

	// write event number
	buf[b] = 1
	b += 1

	b += 1 // padding

	b += 2 // skip sequence number

	xgb.Put32(buf[b:], uint32(v.Drawable))
	b += 4

	return buf
}

// SequenceId returns the sequence id attached to the InvalidateBuffers event.
// Events without a sequence number (KeymapNotify) return 0.
// This is mostly used internally.
func (v InvalidateBuffersEvent) SequenceId() uint16 {
	return v.Sequence
}

// String is a rudimentary string representation of InvalidateBuffersEvent.
func (v InvalidateBuffersEvent) String() string {
	fieldVals := make([]string, 0, 2)
	fieldVals = append(fieldVals, xgb.Sprintf("Sequence: %d", v.Sequence))
	fieldVals = append(fieldVals, xgb.Sprintf("Drawable: %d", v.Drawable))
	return "InvalidateBuffers {" + xgb.StringsJoin(fieldVals, ", ") + "}"
}

func init() {
	xgb.NewExtEventFuncs["DRI2"][1] = InvalidateBuffersEventNew
}

// Skipping definition for base type 'Bool'

// Skipping definition for base type 'Byte'

// Skipping definition for base type 'Card8'

// Skipping definition for base type 'Char'

// Skipping definition for base type 'Void'

// Skipping definition for base type 'Double'

// Skipping definition for base type 'Float'

// Skipping definition for base type 'Int16'

// Skipping definition for base type 'Int32'

// Skipping definition for base type 'Int8'

// Skipping definition for base type 'Card16'

// Skipping definition for base type 'Card32'

// AuthenticateCookie is a cookie used only for Authenticate requests.
type AuthenticateCookie struct {
	*xgb.Cookie
}

// Authenticate sends a checked request.
// If an error occurs, it will be returned with the reply by calling AuthenticateCookie.Reply()
func Authenticate(c *xgb.Conn, Window xproto.Window, Magic uint32) AuthenticateCookie {
	c.ExtLock.RLock()
	defer c.ExtLock.RUnlock()
	if _, ok := c.Extensions["DRI2"]; !ok {
		panic("Cannot issue request 'Authenticate' using the uninitialized extension 'DRI2'. dri2.Init(connObj) must be called first.")
	}
	cookie := c.NewCookie(true, true)
	c.NewRequest(authenticateRequest(c, Window, Magic), cookie)
	return AuthenticateCookie{cookie}
}

// AuthenticateUnchecked sends an unchecked request.
// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent.
func AuthenticateUnchecked(c *xgb.Conn, Window xproto.Window, Magic uint32) AuthenticateCookie {
	c.ExtLock.RLock()
	defer c.ExtLock.RUnlock()
	if _, ok := c.Extensions["DRI2"]; !ok {
		panic("Cannot issue request 'Authenticate' using the uninitialized extension 'DRI2'. dri2.Init(connObj) must be called first.")
	}
	cookie := c.NewCookie(false, true)
	c.NewRequest(authenticateRequest(c, Window, Magic), cookie)
	return AuthenticateCookie{cookie}
}

// AuthenticateReply represents the data returned from a Authenticate request.
type AuthenticateReply struct {
	Sequence uint16 // sequence number of the request for this reply
	Length   uint32 // number of bytes in this reply
	// padding: 1 bytes
	Authenticated uint32
}

// Reply blocks and returns the reply data for a Authenticate request.
func (cook AuthenticateCookie) Reply() (*AuthenticateReply, error) {
	buf, err := cook.Cookie.Reply()
	if err != nil {
		return nil, err
	}
	if buf == nil {
		return nil, nil
	}
	return authenticateReply(buf), nil
}

// authenticateReply reads a byte slice into a AuthenticateReply value.
func authenticateReply(buf []byte) *AuthenticateReply {
	v := new(AuthenticateReply)
	b := 1 // skip reply determinant

	b += 1 // padding

	v.Sequence = xgb.Get16(buf[b:])
	b += 2

	v.Length = xgb.Get32(buf[b:]) // 4-byte units
	b += 4

	v.Authenticated = xgb.Get32(buf[b:])
	b += 4

	return v
}

// Write request to wire for Authenticate
// authenticateRequest writes a Authenticate request to a byte slice.
func authenticateRequest(c *xgb.Conn, Window xproto.Window, Magic uint32) []byte {
	size := 12
	b := 0
	buf := make([]byte, size)

	c.ExtLock.RLock()
	buf[b] = c.Extensions["DRI2"]
	c.ExtLock.RUnlock()
	b += 1

	buf[b] = 2 // request opcode
	b += 1

	xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units
	b += 2

	xgb.Put32(buf[b:], uint32(Window))
	b += 4

	xgb.Put32(buf[b:], Magic)
	b += 4

	return buf
}

// ConnectCookie is a cookie used only for Connect requests.
type ConnectCookie struct {
	*xgb.Cookie
}

// Connect sends a checked request.
// If an error occurs, it will be returned with the reply by calling ConnectCookie.Reply()
func Connect(c *xgb.Conn, Window xproto.Window, DriverType uint32) ConnectCookie {
	c.ExtLock.RLock()
	defer c.ExtLock.RUnlock()
	if _, ok := c.Extensions["DRI2"]; !ok {
		panic("Cannot issue request 'Connect' using the uninitialized extension 'DRI2'. dri2.Init(connObj) must be called first.")
	}
	cookie := c.NewCookie(true, true)
	c.NewRequest(connectRequest(c, Window, DriverType), cookie)
	return ConnectCookie{cookie}
}

// ConnectUnchecked sends an unchecked request.
// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent.
func ConnectUnchecked(c *xgb.Conn, Window xproto.Window, DriverType uint32) ConnectCookie {
	c.ExtLock.RLock()
	defer c.ExtLock.RUnlock()
	if _, ok := c.Extensions["DRI2"]; !ok {
		panic("Cannot issue request 'Connect' using the uninitialized extension 'DRI2'. dri2.Init(connObj) must be called first.")
	}
	cookie := c.NewCookie(false, true)
	c.NewRequest(connectRequest(c, Window, DriverType), cookie)
	return ConnectCookie{cookie}
}

// ConnectReply represents the data returned from a Connect request.
type ConnectReply struct {
	Sequence uint16 // sequence number of the request for this reply
	Length   uint32 // number of bytes in this reply
	// padding: 1 bytes
	DriverNameLength uint32
	DeviceNameLength uint32
	// padding: 16 bytes
	DriverName   string // size: xgb.Pad((int(DriverNameLength) * 1))
	AlignmentPad []byte // size: xgb.Pad(((((int(DriverNameLength) + 3) & -4) - int(DriverNameLength)) * 1))
	DeviceName   string // size: xgb.Pad((int(DeviceNameLength) * 1))
}

// Reply blocks and returns the reply data for a Connect request.
func (cook ConnectCookie) Reply() (*ConnectReply, error) {
	buf, err := cook.Cookie.Reply()
	if err != nil {
		return nil, err
	}
	if buf == nil {
		return nil, nil
	}
	return connectReply(buf), nil
}

// connectReply reads a byte slice into a ConnectReply value.
func connectReply(buf []byte) *ConnectReply {
	v := new(ConnectReply)
	b := 1 // skip reply determinant

	b += 1 // padding

	v.Sequence = xgb.Get16(buf[b:])
	b += 2

	v.Length = xgb.Get32(buf[b:]) // 4-byte units
	b += 4

	v.DriverNameLength = xgb.Get32(buf[b:])
	b += 4

	v.DeviceNameLength = xgb.Get32(buf[b:])
	b += 4

	b += 16 // padding

	{
		byteString := make([]byte, v.DriverNameLength)
		copy(byteString[:v.DriverNameLength], buf[b:])
		v.DriverName = string(byteString)
		b += int(v.DriverNameLength)
	}

	v.AlignmentPad = make([]byte, (((int(v.DriverNameLength) + 3) & -4) - int(v.DriverNameLength)))
	copy(v.AlignmentPad[:(((int(v.DriverNameLength)+3)&-4)-int(v.DriverNameLength))], buf[b:])
	b += int((((int(v.DriverNameLength) + 3) & -4) - int(v.DriverNameLength)))

	{
		byteString := make([]byte, v.DeviceNameLength)
		copy(byteString[:v.DeviceNameLength], buf[b:])
		v.DeviceName = string(byteString)
		b += int(v.DeviceNameLength)
	}

	return v
}

// Write request to wire for Connect
// connectRequest writes a Connect request to a byte slice.
func connectRequest(c *xgb.Conn, Window xproto.Window, DriverType uint32) []byte {
	size := 12
	b := 0
	buf := make([]byte, size)

	c.ExtLock.RLock()
	buf[b] = c.Extensions["DRI2"]
	c.ExtLock.RUnlock()
	b += 1

	buf[b] = 1 // request opcode
	b += 1

	xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units
	b += 2

	xgb.Put32(buf[b:], uint32(Window))
	b += 4

	xgb.Put32(buf[b:], DriverType)
	b += 4

	return buf
}

// CopyRegionCookie is a cookie used only for CopyRegion requests.
type CopyRegionCookie struct {
	*xgb.Cookie
}

// CopyRegion sends a checked request.
// If an error occurs, it will be returned with the reply by calling CopyRegionCookie.Reply()
func CopyRegion(c *xgb.Conn, Drawable xproto.Drawable, Region uint32, Dest uint32, Src uint32) CopyRegionCookie {
	c.ExtLock.RLock()
	defer c.ExtLock.RUnlock()
	if _, ok := c.Extensions["DRI2"]; !ok {
		panic("Cannot issue request 'CopyRegion' using the uninitialized extension 'DRI2'. dri2.Init(connObj) must be called first.")
	}
	cookie := c.NewCookie(true, true)
	c.NewRequest(copyRegionRequest(c, Drawable, Region, Dest, Src), cookie)
	return CopyRegionCookie{cookie}
}

// CopyRegionUnchecked sends an unchecked request.
// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent.
func CopyRegionUnchecked(c *xgb.Conn, Drawable xproto.Drawable, Region uint32, Dest uint32, Src uint32) CopyRegionCookie {
	c.ExtLock.RLock()
	defer c.ExtLock.RUnlock()
	if _, ok := c.Extensions["DRI2"]; !ok {
		panic("Cannot issue request 'CopyRegion' using the uninitialized extension 'DRI2'. dri2.Init(connObj) must be called first.")
	}
	cookie := c.NewCookie(false, true)
	c.NewRequest(copyRegionRequest(c, Drawable, Region, Dest, Src), cookie)
	return CopyRegionCookie{cookie}
}

// CopyRegionReply represents the data returned from a CopyRegion request.
type CopyRegionReply struct {
	Sequence uint16 // sequence number of the request for this reply
	Length   uint32 // number of bytes in this reply
	// padding: 1 bytes
}

// Reply blocks and returns the reply data for a CopyRegion request.
func (cook CopyRegionCookie) Reply() (*CopyRegionReply, error) {
	buf, err := cook.Cookie.Reply()
	if err != nil {
		return nil, err
	}
	if buf == nil {
		return nil, nil
	}
	return copyRegionReply(buf), nil
}

// copyRegionReply reads a byte slice into a CopyRegionReply value.
func copyRegionReply(buf []byte) *CopyRegionReply {
	v := new(CopyRegionReply)
	b := 1 // skip reply determinant

	b += 1 // padding

	v.Sequence = xgb.Get16(buf[b:])
	b += 2

	v.Length = xgb.Get32(buf[b:]) // 4-byte units
	b += 4

	return v
}

// Write request to wire for CopyRegion
// copyRegionRequest writes a CopyRegion request to a byte slice.
func copyRegionRequest(c *xgb.Conn, Drawable xproto.Drawable, Region uint32, Dest uint32, Src uint32) []byte {
	size := 20
	b := 0
	buf := make([]byte, size)

	c.ExtLock.RLock()
	buf[b] = c.Extensions["DRI2"]
	c.ExtLock.RUnlock()
	b += 1

	buf[b] = 6 // request opcode
	b += 1

	xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units
	b += 2

	xgb.Put32(buf[b:], uint32(Drawable))
	b += 4

	xgb.Put32(buf[b:], Region)
	b += 4

	xgb.Put32(buf[b:], Dest)
	b += 4

	xgb.Put32(buf[b:], Src)
	b += 4

	return buf
}

// CreateDrawableCookie is a cookie used only for CreateDrawable requests.
type CreateDrawableCookie struct {
	*xgb.Cookie
}

// CreateDrawable sends an unchecked request.
// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent.
func CreateDrawable(c *xgb.Conn, Drawable xproto.Drawable) CreateDrawableCookie {
	c.ExtLock.RLock()
	defer c.ExtLock.RUnlock()
	if _, ok := c.Extensions["DRI2"]; !ok {
		panic("Cannot issue request 'CreateDrawable' using the uninitialized extension 'DRI2'. dri2.Init(connObj) must be called first.")
	}
	cookie := c.NewCookie(false, false)
	c.NewRequest(createDrawableRequest(c, Drawable), cookie)
	return CreateDrawableCookie{cookie}
}

// CreateDrawableChecked sends a checked request.
// If an error occurs, it can be retrieved using CreateDrawableCookie.Check()
func CreateDrawableChecked(c *xgb.Conn, Drawable xproto.Drawable) CreateDrawableCookie {
	c.ExtLock.RLock()
	defer c.ExtLock.RUnlock()
	if _, ok := c.Extensions["DRI2"]; !ok {
		panic("Cannot issue request 'CreateDrawable' using the uninitialized extension 'DRI2'. dri2.Init(connObj) must be called first.")
	}
	cookie := c.NewCookie(true, false)
	c.NewRequest(createDrawableRequest(c, Drawable), cookie)
	return CreateDrawableCookie{cookie}
}

// Check returns an error if one occurred for checked requests that are not expecting a reply.
// This cannot be called for requests expecting a reply, nor for unchecked requests.
func (cook CreateDrawableCookie) Check() error {
	return cook.Cookie.Check()
}

// Write request to wire for CreateDrawable
// createDrawableRequest writes a CreateDrawable request to a byte slice.
func createDrawableRequest(c *xgb.Conn, Drawable xproto.Drawable) []byte {
	size := 8
	b := 0
	buf := make([]byte, size)

	c.ExtLock.RLock()
	buf[b] = c.Extensions["DRI2"]
	c.ExtLock.RUnlock()
	b += 1

	buf[b] = 3 // request opcode
	b += 1

	xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units
	b += 2

	xgb.Put32(buf[b:], uint32(Drawable))
	b += 4

	return buf
}

// DestroyDrawableCookie is a cookie used only for DestroyDrawable requests.
type DestroyDrawableCookie struct {
	*xgb.Cookie
}

// DestroyDrawable sends an unchecked request.
// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent.
func DestroyDrawable(c *xgb.Conn, Drawable xproto.Drawable) DestroyDrawableCookie {
	c.ExtLock.RLock()
	defer c.ExtLock.RUnlock()
	if _, ok := c.Extensions["DRI2"]; !ok {
		panic("Cannot issue request 'DestroyDrawable' using the uninitialized extension 'DRI2'. dri2.Init(connObj) must be called first.")
	}
	cookie := c.NewCookie(false, false)
	c.NewRequest(destroyDrawableRequest(c, Drawable), cookie)
	return DestroyDrawableCookie{cookie}
}

// DestroyDrawableChecked sends a checked request.
// If an error occurs, it can be retrieved using DestroyDrawableCookie.Check()
func DestroyDrawableChecked(c *xgb.Conn, Drawable xproto.Drawable) DestroyDrawableCookie {
	c.ExtLock.RLock()
	defer c.ExtLock.RUnlock()
	if _, ok := c.Extensions["DRI2"]; !ok {
		panic("Cannot issue request 'DestroyDrawable' using the uninitialized extension 'DRI2'. dri2.Init(connObj) must be called first.")
	}
	cookie := c.NewCookie(true, false)
	c.NewRequest(destroyDrawableRequest(c, Drawable), cookie)
	return DestroyDrawableCookie{cookie}
}

// Check returns an error if one occurred for checked requests that are not expecting a reply.
// This cannot be called for requests expecting a reply, nor for unchecked requests.
func (cook DestroyDrawableCookie) Check() error {
	return cook.Cookie.Check()
}

// Write request to wire for DestroyDrawable
// destroyDrawableRequest writes a DestroyDrawable request to a byte slice.
func destroyDrawableRequest(c *xgb.Conn, Drawable xproto.Drawable) []byte {
	size := 8
	b := 0
	buf := make([]byte, size)

	c.ExtLock.RLock()
	buf[b] = c.Extensions["DRI2"]
	c.ExtLock.RUnlock()
	b += 1

	buf[b] = 4 // request opcode
	b += 1

	xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units
	b += 2

	xgb.Put32(buf[b:], uint32(Drawable))
	b += 4

	return buf
}

// GetBuffersCookie is a cookie used only for GetBuffers requests.
type GetBuffersCookie struct {
	*xgb.Cookie
}

// GetBuffers sends a checked request.
// If an error occurs, it will be returned with the reply by calling GetBuffersCookie.Reply()
func GetBuffers(c *xgb.Conn, Drawable xproto.Drawable, Count uint32, Attachments []uint32) GetBuffersCookie {
	c.ExtLock.RLock()
	defer c.ExtLock.RUnlock()
	if _, ok := c.Extensions["DRI2"]; !ok {
		panic("Cannot issue request 'GetBuffers' using the uninitialized extension 'DRI2'. dri2.Init(connObj) must be called first.")
	}
	cookie := c.NewCookie(true, true)
	c.NewRequest(getBuffersRequest(c, Drawable, Count, Attachments), cookie)
	return GetBuffersCookie{cookie}
}

// GetBuffersUnchecked sends an unchecked request.
// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent.
func GetBuffersUnchecked(c *xgb.Conn, Drawable xproto.Drawable, Count uint32, Attachments []uint32) GetBuffersCookie {
	c.ExtLock.RLock()
	defer c.ExtLock.RUnlock()
	if _, ok := c.Extensions["DRI2"]; !ok {
		panic("Cannot issue request 'GetBuffers' using the uninitialized extension 'DRI2'. dri2.Init(connObj) must be called first.")
	}
	cookie := c.NewCookie(false, true)
	c.NewRequest(getBuffersRequest(c, Drawable, Count, Attachments), cookie)
	return GetBuffersCookie{cookie}
}

// GetBuffersReply represents the data returned from a GetBuffers request.
type GetBuffersReply struct {
	Sequence uint16 // sequence number of the request for this reply
	Length   uint32 // number of bytes in this reply
	// padding: 1 bytes
	Width  uint32
	Height uint32
	Count  uint32
	// padding: 12 bytes
	Buffers []DRI2Buffer // size: xgb.Pad((int(Count) * 20))
}

// Reply blocks and returns the reply data for a GetBuffers request.
func (cook GetBuffersCookie) Reply() (*GetBuffersReply, error) {
	buf, err := cook.Cookie.Reply()
	if err != nil {
		return nil, err
	}
	if buf == nil {
		return nil, nil
	}
	return getBuffersReply(buf), nil
}

// getBuffersReply reads a byte slice into a GetBuffersReply value.
func getBuffersReply(buf []byte) *GetBuffersReply {
	v := new(GetBuffersReply)
	b := 1 // skip reply determinant

	b += 1 // padding

	v.Sequence = xgb.Get16(buf[b:])
	b += 2

	v.Length = xgb.Get32(buf[b:]) // 4-byte units
	b += 4

	v.Width = xgb.Get32(buf[b:])
	b += 4

	v.Height = xgb.Get32(buf[b:])
	b += 4

	v.Count = xgb.Get32(buf[b:])
	b += 4

	b += 12 // padding

	v.Buffers = make([]DRI2Buffer, v.Count)
	b += DRI2BufferReadList(buf[b:], v.Buffers)

	return v
}

// Write request to wire for GetBuffers
// getBuffersRequest writes a GetBuffers request to a byte slice.
func getBuffersRequest(c *xgb.Conn, Drawable xproto.Drawable, Count uint32, Attachments []uint32) []byte {
	size := xgb.Pad((12 + xgb.Pad((len(Attachments) * 4))))
	b := 0
	buf := make([]byte, size)

	c.ExtLock.RLock()
	buf[b] = c.Extensions["DRI2"]
	c.ExtLock.RUnlock()
	b += 1

	buf[b] = 5 // request opcode
	b += 1

	xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units
	b += 2

	xgb.Put32(buf[b:], uint32(Drawable))
	b += 4

	xgb.Put32(buf[b:], Count)
	b += 4

	for i := 0; i < int(len(Attachments)); i++ {
		xgb.Put32(buf[b:], Attachments[i])
		b += 4
	}

	return buf
}

// GetBuffersWithFormatCookie is a cookie used only for GetBuffersWithFormat requests.
type GetBuffersWithFormatCookie struct {
	*xgb.Cookie
}

// GetBuffersWithFormat sends a checked request.
// If an error occurs, it will be returned with the reply by calling GetBuffersWithFormatCookie.Reply()
func GetBuffersWithFormat(c *xgb.Conn, Drawable xproto.Drawable, Count uint32, Attachments []AttachFormat) GetBuffersWithFormatCookie {
	c.ExtLock.RLock()
	defer c.ExtLock.RUnlock()
	if _, ok := c.Extensions["DRI2"]; !ok {
		panic("Cannot issue request 'GetBuffersWithFormat' using the uninitialized extension 'DRI2'. dri2.Init(connObj) must be called first.")
	}
	cookie := c.NewCookie(true, true)
	c.NewRequest(getBuffersWithFormatRequest(c, Drawable, Count, Attachments), cookie)
	return GetBuffersWithFormatCookie{cookie}
}

// GetBuffersWithFormatUnchecked sends an unchecked request.
// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent.
func GetBuffersWithFormatUnchecked(c *xgb.Conn, Drawable xproto.Drawable, Count uint32, Attachments []AttachFormat) GetBuffersWithFormatCookie {
	c.ExtLock.RLock()
	defer c.ExtLock.RUnlock()
	if _, ok := c.Extensions["DRI2"]; !ok {
		panic("Cannot issue request 'GetBuffersWithFormat' using the uninitialized extension 'DRI2'. dri2.Init(connObj) must be called first.")
	}
	cookie := c.NewCookie(false, true)
	c.NewRequest(getBuffersWithFormatRequest(c, Drawable, Count, Attachments), cookie)
	return GetBuffersWithFormatCookie{cookie}
}

// GetBuffersWithFormatReply represents the data returned from a GetBuffersWithFormat request.
type GetBuffersWithFormatReply struct {
	Sequence uint16 // sequence number of the request for this reply
	Length   uint32 // number of bytes in this reply
	// padding: 1 bytes
	Width  uint32
	Height uint32
	Count  uint32
	// padding: 12 bytes
	Buffers []DRI2Buffer // size: xgb.Pad((int(Count) * 20))
}

// Reply blocks and returns the reply data for a GetBuffersWithFormat request.
func (cook GetBuffersWithFormatCookie) Reply() (*GetBuffersWithFormatReply, error) {
	buf, err := cook.Cookie.Reply()
	if err != nil {
		return nil, err
	}
	if buf == nil {
		return nil, nil
	}
	return getBuffersWithFormatReply(buf), nil
}

// getBuffersWithFormatReply reads a byte slice into a GetBuffersWithFormatReply value.
func getBuffersWithFormatReply(buf []byte) *GetBuffersWithFormatReply {
	v := new(GetBuffersWithFormatReply)
	b := 1 // skip reply determinant

	b += 1 // padding

	v.Sequence = xgb.Get16(buf[b:])
	b += 2

	v.Length = xgb.Get32(buf[b:]) // 4-byte units
	b += 4

	v.Width = xgb.Get32(buf[b:])
	b += 4

	v.Height = xgb.Get32(buf[b:])
	b += 4

	v.Count = xgb.Get32(buf[b:])
	b += 4

	b += 12 // padding

	v.Buffers = make([]DRI2Buffer, v.Count)
	b += DRI2BufferReadList(buf[b:], v.Buffers)

	return v
}

// Write request to wire for GetBuffersWithFormat
// getBuffersWithFormatRequest writes a GetBuffersWithFormat request to a byte slice.
func getBuffersWithFormatRequest(c *xgb.Conn, Drawable xproto.Drawable, Count uint32, Attachments []AttachFormat) []byte {
	size := xgb.Pad((12 + xgb.Pad((len(Attachments) * 8))))
	b := 0
	buf := make([]byte, size)

	c.ExtLock.RLock()
	buf[b] = c.Extensions["DRI2"]
	c.ExtLock.RUnlock()
	b += 1

	buf[b] = 7 // request opcode
	b += 1

	xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units
	b += 2

	xgb.Put32(buf[b:], uint32(Drawable))
	b += 4

	xgb.Put32(buf[b:], Count)
	b += 4

	b += AttachFormatListBytes(buf[b:], Attachments)

	return buf
}

// GetMSCCookie is a cookie used only for GetMSC requests.
type GetMSCCookie struct {
	*xgb.Cookie
}

// GetMSC sends a checked request.
// If an error occurs, it will be returned with the reply by calling GetMSCCookie.Reply()
func GetMSC(c *xgb.Conn, Drawable xproto.Drawable) GetMSCCookie {
	c.ExtLock.RLock()
	defer c.ExtLock.RUnlock()
	if _, ok := c.Extensions["DRI2"]; !ok {
		panic("Cannot issue request 'GetMSC' using the uninitialized extension 'DRI2'. dri2.Init(connObj) must be called first.")
	}
	cookie := c.NewCookie(true, true)
	c.NewRequest(getMSCRequest(c, Drawable), cookie)
	return GetMSCCookie{cookie}
}

// GetMSCUnchecked sends an unchecked request.
// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent.
func GetMSCUnchecked(c *xgb.Conn, Drawable xproto.Drawable) GetMSCCookie {
	c.ExtLock.RLock()
	defer c.ExtLock.RUnlock()
	if _, ok := c.Extensions["DRI2"]; !ok {
		panic("Cannot issue request 'GetMSC' using the uninitialized extension 'DRI2'. dri2.Init(connObj) must be called first.")
	}
	cookie := c.NewCookie(false, true)
	c.NewRequest(getMSCRequest(c, Drawable), cookie)
	return GetMSCCookie{cookie}
}

// GetMSCReply represents the data returned from a GetMSC request.
type GetMSCReply struct {
	Sequence uint16 // sequence number of the request for this reply
	Length   uint32 // number of bytes in this reply
	// padding: 1 bytes
	UstHi uint32
	UstLo uint32
	MscHi uint32
	MscLo uint32
	SbcHi uint32
	SbcLo uint32
}

// Reply blocks and returns the reply data for a GetMSC request.
func (cook GetMSCCookie) Reply() (*GetMSCReply, error) {
	buf, err := cook.Cookie.Reply()
	if err != nil {
		return nil, err
	}
	if buf == nil {
		return nil, nil
	}
	return getMSCReply(buf), nil
}

// getMSCReply reads a byte slice into a GetMSCReply value.
func getMSCReply(buf []byte) *GetMSCReply {
	v := new(GetMSCReply)
	b := 1 // skip reply determinant

	b += 1 // padding

	v.Sequence = xgb.Get16(buf[b:])
	b += 2

	v.Length = xgb.Get32(buf[b:]) // 4-byte units
	b += 4

	v.UstHi = xgb.Get32(buf[b:])
	b += 4

	v.UstLo = xgb.Get32(buf[b:])
	b += 4

	v.MscHi = xgb.Get32(buf[b:])
	b += 4

	v.MscLo = xgb.Get32(buf[b:])
	b += 4

	v.SbcHi = xgb.Get32(buf[b:])
	b += 4

	v.SbcLo = xgb.Get32(buf[b:])
	b += 4

	return v
}

// Write request to wire for GetMSC
// getMSCRequest writes a GetMSC request to a byte slice.
func getMSCRequest(c *xgb.Conn, Drawable xproto.Drawable) []byte {
	size := 8
	b := 0
	buf := make([]byte, size)

	c.ExtLock.RLock()
	buf[b] = c.Extensions["DRI2"]
	c.ExtLock.RUnlock()
	b += 1

	buf[b] = 9 // request opcode
	b += 1

	xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units
	b += 2

	xgb.Put32(buf[b:], uint32(Drawable))
	b += 4

	return buf
}

// GetParamCookie is a cookie used only for GetParam requests.
type GetParamCookie struct {
	*xgb.Cookie
}

// GetParam sends a checked request.
// If an error occurs, it will be returned with the reply by calling GetParamCookie.Reply()
func GetParam(c *xgb.Conn, Drawable xproto.Drawable, Param uint32) GetParamCookie {
	c.ExtLock.RLock()
	defer c.ExtLock.RUnlock()
	if _, ok := c.Extensions["DRI2"]; !ok {
		panic("Cannot issue request 'GetParam' using the uninitialized extension 'DRI2'. dri2.Init(connObj) must be called first.")
	}
	cookie := c.NewCookie(true, true)
	c.NewRequest(getParamRequest(c, Drawable, Param), cookie)
	return GetParamCookie{cookie}
}

// GetParamUnchecked sends an unchecked request.
// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent.
func GetParamUnchecked(c *xgb.Conn, Drawable xproto.Drawable, Param uint32) GetParamCookie {
	c.ExtLock.RLock()
	defer c.ExtLock.RUnlock()
	if _, ok := c.Extensions["DRI2"]; !ok {
		panic("Cannot issue request 'GetParam' using the uninitialized extension 'DRI2'. dri2.Init(connObj) must be called first.")
	}
	cookie := c.NewCookie(false, true)
	c.NewRequest(getParamRequest(c, Drawable, Param), cookie)
	return GetParamCookie{cookie}
}

// GetParamReply represents the data returned from a GetParam request.
type GetParamReply struct {
	Sequence          uint16 // sequence number of the request for this reply
	Length            uint32 // number of bytes in this reply
	IsParamRecognized bool
	ValueHi           uint32
	ValueLo           uint32
}

// Reply blocks and returns the reply data for a GetParam request.
func (cook GetParamCookie) Reply() (*GetParamReply, error) {
	buf, err := cook.Cookie.Reply()
	if err != nil {
		return nil, err
	}
	if buf == nil {
		return nil, nil
	}
	return getParamReply(buf), nil
}

// getParamReply reads a byte slice into a GetParamReply value.
func getParamReply(buf []byte) *GetParamReply {
	v := new(GetParamReply)
	b := 1 // skip reply determinant

	if buf[b] == 1 {
		v.IsParamRecognized = true
	} else {
		v.IsParamRecognized = false
	}
	b += 1

	v.Sequence = xgb.Get16(buf[b:])
	b += 2

	v.Length = xgb.Get32(buf[b:]) // 4-byte units
	b += 4

	v.ValueHi = xgb.Get32(buf[b:])
	b += 4

	v.ValueLo = xgb.Get32(buf[b:])
	b += 4

	return v
}

// Write request to wire for GetParam
// getParamRequest writes a GetParam request to a byte slice.
func getParamRequest(c *xgb.Conn, Drawable xproto.Drawable, Param uint32) []byte {
	size := 12
	b := 0
	buf := make([]byte, size)

	c.ExtLock.RLock()
	buf[b] = c.Extensions["DRI2"]
	c.ExtLock.RUnlock()
	b += 1

	buf[b] = 13 // request opcode
	b += 1

	xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units
	b += 2

	xgb.Put32(buf[b:], uint32(Drawable))
	b += 4

	xgb.Put32(buf[b:], Param)
	b += 4

	return buf
}

// QueryVersionCookie is a cookie used only for QueryVersion requests.
type QueryVersionCookie struct {
	*xgb.Cookie
}

// QueryVersion sends a checked request.
// If an error occurs, it will be returned with the reply by calling QueryVersionCookie.Reply()
func QueryVersion(c *xgb.Conn, MajorVersion uint32, MinorVersion uint32) QueryVersionCookie {
	c.ExtLock.RLock()
	defer c.ExtLock.RUnlock()
	if _, ok := c.Extensions["DRI2"]; !ok {
		panic("Cannot issue request 'QueryVersion' using the uninitialized extension 'DRI2'. dri2.Init(connObj) must be called first.")
	}
	cookie := c.NewCookie(true, true)
	c.NewRequest(queryVersionRequest(c, MajorVersion, MinorVersion), cookie)
	return QueryVersionCookie{cookie}
}

// QueryVersionUnchecked sends an unchecked request.
// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent.
func QueryVersionUnchecked(c *xgb.Conn, MajorVersion uint32, MinorVersion uint32) QueryVersionCookie {
	c.ExtLock.RLock()
	defer c.ExtLock.RUnlock()
	if _, ok := c.Extensions["DRI2"]; !ok {
		panic("Cannot issue request 'QueryVersion' using the uninitialized extension 'DRI2'. dri2.Init(connObj) must be called first.")
	}
	cookie := c.NewCookie(false, true)
	c.NewRequest(queryVersionRequest(c, MajorVersion, MinorVersion), cookie)
	return QueryVersionCookie{cookie}
}

// QueryVersionReply represents the data returned from a QueryVersion request.
type QueryVersionReply struct {
	Sequence uint16 // sequence number of the request for this reply
	Length   uint32 // number of bytes in this reply
	// padding: 1 bytes
	MajorVersion uint32
	MinorVersion uint32
}

// Reply blocks and returns the reply data for a QueryVersion request.
func (cook QueryVersionCookie) Reply() (*QueryVersionReply, error) {
	buf, err := cook.Cookie.Reply()
	if err != nil {
		return nil, err
	}
	if buf == nil {
		return nil, nil
	}
	return queryVersionReply(buf), nil
}

// queryVersionReply reads a byte slice into a QueryVersionReply value.
func queryVersionReply(buf []byte) *QueryVersionReply {
	v := new(QueryVersionReply)
	b := 1 // skip reply determinant

	b += 1 // padding

	v.Sequence = xgb.Get16(buf[b:])
	b += 2

	v.Length = xgb.Get32(buf[b:]) // 4-byte units
	b += 4

	v.MajorVersion = xgb.Get32(buf[b:])
	b += 4

	v.MinorVersion = xgb.Get32(buf[b:])
	b += 4

	return v
}

// Write request to wire for QueryVersion
// queryVersionRequest writes a QueryVersion request to a byte slice.
func queryVersionRequest(c *xgb.Conn, MajorVersion uint32, MinorVersion uint32) []byte {
	size := 12
	b := 0
	buf := make([]byte, size)

	c.ExtLock.RLock()
	buf[b] = c.Extensions["DRI2"]
	c.ExtLock.RUnlock()
	b += 1

	buf[b] = 0 // request opcode
	b += 1

	xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units
	b += 2

	xgb.Put32(buf[b:], MajorVersion)
	b += 4

	xgb.Put32(buf[b:], MinorVersion)
	b += 4

	return buf
}

// SwapBuffersCookie is a cookie used only for SwapBuffers requests.
type SwapBuffersCookie struct {
	*xgb.Cookie
}

// SwapBuffers sends a checked request.
// If an error occurs, it will be returned with the reply by calling SwapBuffersCookie.Reply()
func SwapBuffers(c *xgb.Conn, Drawable xproto.Drawable, TargetMscHi uint32, TargetMscLo uint32, DivisorHi uint32, DivisorLo uint32, RemainderHi uint32, RemainderLo uint32) SwapBuffersCookie {
	c.ExtLock.RLock()
	defer c.ExtLock.RUnlock()
	if _, ok := c.Extensions["DRI2"]; !ok {
		panic("Cannot issue request 'SwapBuffers' using the uninitialized extension 'DRI2'. dri2.Init(connObj) must be called first.")
	}
	cookie := c.NewCookie(true, true)
	c.NewRequest(swapBuffersRequest(c, Drawable, TargetMscHi, TargetMscLo, DivisorHi, DivisorLo, RemainderHi, RemainderLo), cookie)
	return SwapBuffersCookie{cookie}
}

// SwapBuffersUnchecked sends an unchecked request.
// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent.
func SwapBuffersUnchecked(c *xgb.Conn, Drawable xproto.Drawable, TargetMscHi uint32, TargetMscLo uint32, DivisorHi uint32, DivisorLo uint32, RemainderHi uint32, RemainderLo uint32) SwapBuffersCookie {
	c.ExtLock.RLock()
	defer c.ExtLock.RUnlock()
	if _, ok := c.Extensions["DRI2"]; !ok {
		panic("Cannot issue request 'SwapBuffers' using the uninitialized extension 'DRI2'. dri2.Init(connObj) must be called first.")
	}
	cookie := c.NewCookie(false, true)
	c.NewRequest(swapBuffersRequest(c, Drawable, TargetMscHi, TargetMscLo, DivisorHi, DivisorLo, RemainderHi, RemainderLo), cookie)
	return SwapBuffersCookie{cookie}
}

// SwapBuffersReply represents the data returned from a SwapBuffers request.
type SwapBuffersReply struct {
	Sequence uint16 // sequence number of the request for this reply
	Length   uint32 // number of bytes in this reply
	// padding: 1 bytes
	SwapHi uint32
	SwapLo uint32
}

// Reply blocks and returns the reply data for a SwapBuffers request.
func (cook SwapBuffersCookie) Reply() (*SwapBuffersReply, error) {
	buf, err := cook.Cookie.Reply()
	if err != nil {
		return nil, err
	}
	if buf == nil {
		return nil, nil
	}
	return swapBuffersReply(buf), nil
}

// swapBuffersReply reads a byte slice into a SwapBuffersReply value.
func swapBuffersReply(buf []byte) *SwapBuffersReply {
	v := new(SwapBuffersReply)
	b := 1 // skip reply determinant

	b += 1 // padding

	v.Sequence = xgb.Get16(buf[b:])
	b += 2

	v.Length = xgb.Get32(buf[b:]) // 4-byte units
	b += 4

	v.SwapHi = xgb.Get32(buf[b:])
	b += 4

	v.SwapLo = xgb.Get32(buf[b:])
	b += 4

	return v
}

// Write request to wire for SwapBuffers
// swapBuffersRequest writes a SwapBuffers request to a byte slice.
func swapBuffersRequest(c *xgb.Conn, Drawable xproto.Drawable, TargetMscHi uint32, TargetMscLo uint32, DivisorHi uint32, DivisorLo uint32, RemainderHi uint32, RemainderLo uint32) []byte {
	size := 32
	b := 0
	buf := make([]byte, size)

	c.ExtLock.RLock()
	buf[b] = c.Extensions["DRI2"]
	c.ExtLock.RUnlock()
	b += 1

	buf[b] = 8 // request opcode
	b += 1

	xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units
	b += 2

	xgb.Put32(buf[b:], uint32(Drawable))
	b += 4

	xgb.Put32(buf[b:], TargetMscHi)
	b += 4

	xgb.Put32(buf[b:], TargetMscLo)
	b += 4

	xgb.Put32(buf[b:], DivisorHi)
	b += 4

	xgb.Put32(buf[b:], DivisorLo)
	b += 4

	xgb.Put32(buf[b:], RemainderHi)
	b += 4

	xgb.Put32(buf[b:], RemainderLo)
	b += 4

	return buf
}

// SwapIntervalCookie is a cookie used only for SwapInterval requests.
type SwapIntervalCookie struct {
	*xgb.Cookie
}

// SwapInterval sends an unchecked request.
// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent.
func SwapInterval(c *xgb.Conn, Drawable xproto.Drawable, Interval uint32) SwapIntervalCookie {
	c.ExtLock.RLock()
	defer c.ExtLock.RUnlock()
	if _, ok := c.Extensions["DRI2"]; !ok {
		panic("Cannot issue request 'SwapInterval' using the uninitialized extension 'DRI2'. dri2.Init(connObj) must be called first.")
	}
	cookie := c.NewCookie(false, false)
	c.NewRequest(swapIntervalRequest(c, Drawable, Interval), cookie)
	return SwapIntervalCookie{cookie}
}

// SwapIntervalChecked sends a checked request.
// If an error occurs, it can be retrieved using SwapIntervalCookie.Check()
func SwapIntervalChecked(c *xgb.Conn, Drawable xproto.Drawable, Interval uint32) SwapIntervalCookie {
	c.ExtLock.RLock()
	defer c.ExtLock.RUnlock()
	if _, ok := c.Extensions["DRI2"]; !ok {
		panic("Cannot issue request 'SwapInterval' using the uninitialized extension 'DRI2'. dri2.Init(connObj) must be called first.")
	}
	cookie := c.NewCookie(true, false)
	c.NewRequest(swapIntervalRequest(c, Drawable, Interval), cookie)
	return SwapIntervalCookie{cookie}
}

// Check returns an error if one occurred for checked requests that are not expecting a reply.
// This cannot be called for requests expecting a reply, nor for unchecked requests.
func (cook SwapIntervalCookie) Check() error {
	return cook.Cookie.Check()
}

// Write request to wire for SwapInterval
// swapIntervalRequest writes a SwapInterval request to a byte slice.
func swapIntervalRequest(c *xgb.Conn, Drawable xproto.Drawable, Interval uint32) []byte {
	size := 12
	b := 0
	buf := make([]byte, size)

	c.ExtLock.RLock()
	buf[b] = c.Extensions["DRI2"]
	c.ExtLock.RUnlock()
	b += 1

	buf[b] = 12 // request opcode
	b += 1

	xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units
	b += 2

	xgb.Put32(buf[b:], uint32(Drawable))
	b += 4

	xgb.Put32(buf[b:], Interval)
	b += 4

	return buf
}

// WaitMSCCookie is a cookie used only for WaitMSC requests.
type WaitMSCCookie struct {
	*xgb.Cookie
}

// WaitMSC sends a checked request.
// If an error occurs, it will be returned with the reply by calling WaitMSCCookie.Reply()
func WaitMSC(c *xgb.Conn, Drawable xproto.Drawable, TargetMscHi uint32, TargetMscLo uint32, DivisorHi uint32, DivisorLo uint32, RemainderHi uint32, RemainderLo uint32) WaitMSCCookie {
	c.ExtLock.RLock()
	defer c.ExtLock.RUnlock()
	if _, ok := c.Extensions["DRI2"]; !ok {
		panic("Cannot issue request 'WaitMSC' using the uninitialized extension 'DRI2'. dri2.Init(connObj) must be called first.")
	}
	cookie := c.NewCookie(true, true)
	c.NewRequest(waitMSCRequest(c, Drawable, TargetMscHi, TargetMscLo, DivisorHi, DivisorLo, RemainderHi, RemainderLo), cookie)
	return WaitMSCCookie{cookie}
}

// WaitMSCUnchecked sends an unchecked request.
// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent.
func WaitMSCUnchecked(c *xgb.Conn, Drawable xproto.Drawable, TargetMscHi uint32, TargetMscLo uint32, DivisorHi uint32, DivisorLo uint32, RemainderHi uint32, RemainderLo uint32) WaitMSCCookie {
	c.ExtLock.RLock()
	defer c.ExtLock.RUnlock()
	if _, ok := c.Extensions["DRI2"]; !ok {
		panic("Cannot issue request 'WaitMSC' using the uninitialized extension 'DRI2'. dri2.Init(connObj) must be called first.")
	}
	cookie := c.NewCookie(false, true)
	c.NewRequest(waitMSCRequest(c, Drawable, TargetMscHi, TargetMscLo, DivisorHi, DivisorLo, RemainderHi, RemainderLo), cookie)
	return WaitMSCCookie{cookie}
}

// WaitMSCReply represents the data returned from a WaitMSC request.
type WaitMSCReply struct {
	Sequence uint16 // sequence number of the request for this reply
	Length   uint32 // number of bytes in this reply
	// padding: 1 bytes
	UstHi uint32
	UstLo uint32
	MscHi uint32
	MscLo uint32
	SbcHi uint32
	SbcLo uint32
}

// Reply blocks and returns the reply data for a WaitMSC request.
func (cook WaitMSCCookie) Reply() (*WaitMSCReply, error) {
	buf, err := cook.Cookie.Reply()
	if err != nil {
		return nil, err
	}
	if buf == nil {
		return nil, nil
	}
	return waitMSCReply(buf), nil
}

// waitMSCReply reads a byte slice into a WaitMSCReply value.
func waitMSCReply(buf []byte) *WaitMSCReply {
	v := new(WaitMSCReply)
	b := 1 // skip reply determinant

	b += 1 // padding

	v.Sequence = xgb.Get16(buf[b:])
	b += 2

	v.Length = xgb.Get32(buf[b:]) // 4-byte units
	b += 4

	v.UstHi = xgb.Get32(buf[b:])
	b += 4

	v.UstLo = xgb.Get32(buf[b:])
	b += 4

	v.MscHi = xgb.Get32(buf[b:])
	b += 4

	v.MscLo = xgb.Get32(buf[b:])
	b += 4

	v.SbcHi = xgb.Get32(buf[b:])
	b += 4

	v.SbcLo = xgb.Get32(buf[b:])
	b += 4

	return v
}

// Write request to wire for WaitMSC
// waitMSCRequest writes a WaitMSC request to a byte slice.
func waitMSCRequest(c *xgb.Conn, Drawable xproto.Drawable, TargetMscHi uint32, TargetMscLo uint32, DivisorHi uint32, DivisorLo uint32, RemainderHi uint32, RemainderLo uint32) []byte {
	size := 32
	b := 0
	buf := make([]byte, size)

	c.ExtLock.RLock()
	buf[b] = c.Extensions["DRI2"]
	c.ExtLock.RUnlock()
	b += 1

	buf[b] = 10 // request opcode
	b += 1

	xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units
	b += 2

	xgb.Put32(buf[b:], uint32(Drawable))
	b += 4

	xgb.Put32(buf[b:], TargetMscHi)
	b += 4

	xgb.Put32(buf[b:], TargetMscLo)
	b += 4

	xgb.Put32(buf[b:], DivisorHi)
	b += 4

	xgb.Put32(buf[b:], DivisorLo)
	b += 4

	xgb.Put32(buf[b:], RemainderHi)
	b += 4

	xgb.Put32(buf[b:], RemainderLo)
	b += 4

	return buf
}

// WaitSBCCookie is a cookie used only for WaitSBC requests.
type WaitSBCCookie struct {
	*xgb.Cookie
}

// WaitSBC sends a checked request.
// If an error occurs, it will be returned with the reply by calling WaitSBCCookie.Reply()
func WaitSBC(c *xgb.Conn, Drawable xproto.Drawable, TargetSbcHi uint32, TargetSbcLo uint32) WaitSBCCookie {
	c.ExtLock.RLock()
	defer c.ExtLock.RUnlock()
	if _, ok := c.Extensions["DRI2"]; !ok {
		panic("Cannot issue request 'WaitSBC' using the uninitialized extension 'DRI2'. dri2.Init(connObj) must be called first.")
	}
	cookie := c.NewCookie(true, true)
	c.NewRequest(waitSBCRequest(c, Drawable, TargetSbcHi, TargetSbcLo), cookie)
	return WaitSBCCookie{cookie}
}

// WaitSBCUnchecked sends an unchecked request.
// If an error occurs, it can only be retrieved using xgb.WaitForEvent or xgb.PollForEvent.
func WaitSBCUnchecked(c *xgb.Conn, Drawable xproto.Drawable, TargetSbcHi uint32, TargetSbcLo uint32) WaitSBCCookie {
	c.ExtLock.RLock()
	defer c.ExtLock.RUnlock()
	if _, ok := c.Extensions["DRI2"]; !ok {
		panic("Cannot issue request 'WaitSBC' using the uninitialized extension 'DRI2'. dri2.Init(connObj) must be called first.")
	}
	cookie := c.NewCookie(false, true)
	c.NewRequest(waitSBCRequest(c, Drawable, TargetSbcHi, TargetSbcLo), cookie)
	return WaitSBCCookie{cookie}
}

// WaitSBCReply represents the data returned from a WaitSBC request.
type WaitSBCReply struct {
	Sequence uint16 // sequence number of the request for this reply
	Length   uint32 // number of bytes in this reply
	// padding: 1 bytes
	UstHi uint32
	UstLo uint32
	MscHi uint32
	MscLo uint32
	SbcHi uint32
	SbcLo uint32
}

// Reply blocks and returns the reply data for a WaitSBC request.
func (cook WaitSBCCookie) Reply() (*WaitSBCReply, error) {
	buf, err := cook.Cookie.Reply()
	if err != nil {
		return nil, err
	}
	if buf == nil {
		return nil, nil
	}
	return waitSBCReply(buf), nil
}

// waitSBCReply reads a byte slice into a WaitSBCReply value.
func waitSBCReply(buf []byte) *WaitSBCReply {
	v := new(WaitSBCReply)
	b := 1 // skip reply determinant

	b += 1 // padding

	v.Sequence = xgb.Get16(buf[b:])
	b += 2

	v.Length = xgb.Get32(buf[b:]) // 4-byte units
	b += 4

	v.UstHi = xgb.Get32(buf[b:])
	b += 4

	v.UstLo = xgb.Get32(buf[b:])
	b += 4

	v.MscHi = xgb.Get32(buf[b:])
	b += 4

	v.MscLo = xgb.Get32(buf[b:])
	b += 4

	v.SbcHi = xgb.Get32(buf[b:])
	b += 4

	v.SbcLo = xgb.Get32(buf[b:])
	b += 4

	return v
}

// Write request to wire for WaitSBC
// waitSBCRequest writes a WaitSBC request to a byte slice.
func waitSBCRequest(c *xgb.Conn, Drawable xproto.Drawable, TargetSbcHi uint32, TargetSbcLo uint32) []byte {
	size := 16
	b := 0
	buf := make([]byte, size)

	c.ExtLock.RLock()
	buf[b] = c.Extensions["DRI2"]
	c.ExtLock.RUnlock()
	b += 1

	buf[b] = 11 // request opcode
	b += 1

	xgb.Put16(buf[b:], uint16(size/4)) // write request size in 4-byte units
	b += 2

	xgb.Put32(buf[b:], uint32(Drawable))
	b += 4

	xgb.Put32(buf[b:], TargetSbcHi)
	b += 4

	xgb.Put32(buf[b:], TargetSbcLo)
	b += 4

	return buf
}
