/* i_width x i_heightのテクスチャを格納するインスタンスを生成します。 * */ public NyARD3dSurface(Microsoft.DirectX.Direct3D.Device i_dev, int i_width, int i_height) { this.m_ref_dev = i_dev; this.m_height = i_height; this.m_width = i_width; this._surface = i_dev.CreateOffscreenPlainSurface(i_width, i_height, Format.X8R8G8B8, Pool.Default); //OK、完成だ。 return; }
private void InitializeDXDevice() { //initialize DirectX device where GlobalVariables.SelectedDisplay 0 is a main monitor or eg. 1 is a second monitor int adapterOrdinal = Manager.Adapters[GlobalVariables.SelectedDisplay].Adapter; Caps caps = Manager.GetDeviceCaps(adapterOrdinal, DeviceType.Hardware); CreateFlags createFlags; if (caps.DeviceCaps.SupportsHardwareTransformAndLight) { createFlags = CreateFlags.HardwareVertexProcessing; } else { createFlags = CreateFlags.SoftwareVertexProcessing; } if (caps.DeviceCaps.SupportsPureDevice && createFlags == CreateFlags.HardwareVertexProcessing) { createFlags |= CreateFlags.PureDevice; } presentParams = new PresentParameters(); presentParams.Windowed = true; //presentParams.SwapEffect = SwapEffect.Discard; presentParams.SwapEffect = SwapEffect.Discard; presentParams.PresentationInterval = PresentInterval.One; presentParams.PresentFlag = PresentFlag.None; presentParams.MultiSample = MultiSampleType.None; //presentParams.DeviceWindowHandle = GetDesktopWindow().Handle; //presentParams.DeviceWindow = User32.GetDesktopWindow(); device = new Device(adapterOrdinal, DeviceType.Hardware, User32.GetDesktopWindow(), createFlags, presentParams); s = device.CreateOffscreenPlainSurface(device.DisplayMode.Width, device.DisplayMode.Height, Format.A8R8G8B8, Pool.SystemMemory); // b = new Bitmap(SurfaceLoader.SaveToStream(ImageFileFormat.Bmp, s)); label36.Text = device.DisplayMode.Width + "x" + device.DisplayMode.Height + "x" + device.DisplayMode.Format + "@" + device.DisplayMode.RefreshRate + "Hz"; }
protected void BlitFromMemoryImpl(PixelBox src, BasicBox dstBox) { // TODO: This currently does way too many copies. We copy // from src to a converted buffer (if needed), then from // converted to a byte array, then into the temporary surface, // and finally from the temporary surface to the real surface. PixelBox converted = src; IntPtr bufPtr = IntPtr.Zero; GCHandle bufGCHandle = new GCHandle(); // convert to pixelbuffer's native format if necessary if (D3DHelper.ConvertEnum(src.Format) == D3D.Format.Unknown) { int bufSize = PixelUtil.GetMemorySize(src.Width, src.Height, src.Depth, format); byte[] newBuffer = new byte[bufSize]; bufGCHandle = GCHandle.Alloc(newBuffer, GCHandleType.Pinned); bufPtr = bufGCHandle.AddrOfPinnedObject(); converted = new PixelBox(src.Width, src.Height, src.Depth, format, bufPtr); PixelUtil.BulkPixelConversion(src, converted); } // int formatBytes = PixelUtil.GetNumElemBytes(converted.Format); Surface tmpSurface = device.CreateOffscreenPlainSurface(converted.Width, converted.Height, D3DHelper.ConvertEnum(converted.Format), Pool.Scratch); int pitch; // Ideally I would be using the Array mechanism here, but that doesn't seem to work GraphicsStream buf = tmpSurface.LockRectangle(LockFlags.NoSystemLock, out pitch); buf.Position = 0; unsafe { int bufSize = PixelUtil.GetMemorySize(converted.Width, converted.Height, converted.Depth, converted.Format); byte * srcPtr = (byte *)converted.Data.ToPointer(); byte[] ugh = new byte[bufSize]; for (int i = 0; i < bufSize; ++i) { ugh[i] = srcPtr[i]; } buf.Write(ugh); } tmpSurface.UnlockRectangle(); buf.Dispose(); //ImageInformation imageInfo = new ImageInformation(); //imageInfo.Format = D3DHelper.ConvertEnum(converted.Format); //imageInfo.Width = converted.Width; //imageInfo.Height = converted.Height; //imageInfo.Depth = converted.Depth; if (surface != null) { // I'm trying to write to surface using the data in converted Rectangle srcRect = ToD3DRectangleExtent(converted); Rectangle destRect = ToD3DRectangle(dstBox); SurfaceLoader.FromSurface(surface, destRect, tmpSurface, srcRect, Filter.None, 0); } else { D3D.Box srcBox = ToD3DBoxExtent(converted); D3D.Box destBox = ToD3DBox(dstBox); Debug.Assert(false, "Volume textures not yet supported"); // VolumeLoader.FromStream(volume, destBox, converted.Data, converted.RowPitch * converted.SlicePitch * formatBytes, srcBox, Filter.None, 0); VolumeLoader.FromStream(volume, destBox, buf, srcBox, Filter.None, 0); } tmpSurface.Dispose(); // If we allocated a buffer for the temporary conversion, free it here // If I used bufPtr to store my temporary data while I converted // it, I need to free it here. This invalidates converted. // My data has already been copied to tmpSurface and then to the // real surface. if (bufGCHandle.IsAllocated) { bufGCHandle.Free(); } if (doMipmapGen) { GenMipmaps(); } }
/// <summary> /// Saves the window contents to a stream. /// </summary> /// <param name="stream">Stream to write the window contents to.</param> public override void Save(Stream stream, PixelFormat requestedFormat) { D3D.Device device = driver.Device; DisplayMode mode = device.DisplayMode; SurfaceDescription desc = new SurfaceDescription(); desc.Width = mode.Width; desc.Height = mode.Height; desc.Format = Format.A8R8G8B8; // create a temp surface which will hold the screen image Surface surface = device.CreateOffscreenPlainSurface( mode.Width, mode.Height, Format.A8R8G8B8, Pool.SystemMemory); // get the entire front buffer. This is SLOW!! device.GetFrontBufferData(0, surface); // if not fullscreen, the front buffer contains the entire desktop image. we need to grab only the portion // that contains our render window if (!IsFullScreen) { // whatever our target control is, we need to walk up the chain and find the parent form Form form = windowHandle.FindForm(); // get the actual screen location of the form System.Drawing.Rectangle rect = form.RectangleToScreen(form.ClientRectangle); desc.Width = width; desc.Height = height; desc.Format = Format.A8R8G8B8; // create a temp surface that is sized the same as our target control Surface tmpSurface = device.CreateOffscreenPlainSurface(rect.Width, rect.Height, Format.A8R8G8B8, Pool.Default); // copy the data from the front buffer to the window sized surface device.UpdateSurface(surface, rect, tmpSurface); // dispose of the prior surface surface.Dispose(); surface = tmpSurface; } int pitch; // lock the surface to grab the data GraphicsStream graphStream = surface.LockRectangle(LockFlags.ReadOnly | LockFlags.NoSystemLock, out pitch); // create an RGB buffer byte[] buffer = new byte[width * height * 3]; int offset = 0, line = 0, count = 0; // gotta copy that data manually since it is in another format (sheesh!) unsafe { byte *data = (byte *)graphStream.InternalData; for (int y = 0; y < desc.Height; y++) { line = y * pitch; for (int x = 0; x < desc.Width; x++) { offset = x * 4; int pixel = line + offset; // Actual format is BRGA for some reason buffer[count++] = data[pixel + 2]; buffer[count++] = data[pixel + 1]; buffer[count++] = data[pixel + 0]; } } } surface.UnlockRectangle(); // dispose of the surface surface.Dispose(); // gotta flip the image real fast Image image = Image.FromDynamicImage(buffer, width, height, PixelFormat.R8G8B8); image.FlipAroundX(); // write the data to the stream provided stream.Write(image.Data, 0, image.Data.Length); }